TypeScript – Interfaces

Interface è una struttura che definisce il contratto nella tua applicazione. Definisce la sintassi che le classi devono seguire. Le classi che derivano da un’interfaccia devono seguire la struttura fornita dalla loro interfaccia.

Il compilatore TypeScript non converte l’interfaccia in JavaScript. Usa l’interfaccia per il controllo dei tipi. Questo è anche conosciuto come “duck typing” o “structural subtyping”.

Un’interfaccia è definita con la parola chiave interface e può includere proprietà e dichiarazioni di metodi usando una funzione o una funzione freccia.

Esempio: Interfaccia

Copia

interface IEmployee { empCode: number; empName: string; getSalary: (number) => number; // arrow function getManagerName(number): string; }

Nell’esempio precedente, l’interfaccia IEmployee include due proprietà empCode e empName. Include anche una dichiarazione di metodo getSalaray che usa una funzione freccia che include un parametro numero e un tipo di ritorno numero. Il metodo getManagerName è dichiarato usando una funzione normale. Questo significa che qualsiasi oggetto di tipo IEmployee deve definire le due proprietà e i due metodi.

Interfaccia come tipo

L’interfaccia in TypeScript può essere usata per definire un tipo e anche per implementarlo nella classe.

La seguente interfaccia IEmployee definisce il tipo di una variabile.

Esempio: Interfaccia come Tipo

Copia

interface KeyPair { key: number; value: string;}let kv1: KeyPair = { key:1, value:"Steve" }; // OKlet kv2: KeyPair = { key:1, val:"Steve" }; // Compiler Error: 'val' doesn't exist in type 'KeyPair'let kv3: KeyPair = { key:1, value:100 }; // Compiler Error: 

Nell’esempio precedente, un’interfaccia KeyPair include due proprietà key e value. Una variabile kv1 è dichiarata come il tipo KeyPair. Quindi, deve seguire la stessa struttura di KeyPair. Significa che solo un oggetto con proprietà key di tipo numero e value di tipo stringa può essere assegnato a una variabile kv1. Il compilatore TypeScript mostrerà un errore se c’è qualche cambiamento nel nome delle proprietà o il tipo di dati è diverso da KeyPair. Un’altra variabile kv2 è anche dichiarata come tipo KeyPair ma il valore assegnato è val invece di value, quindi questo causerà un errore. Allo stesso modo, kv3 assegna un numero alla proprietà value, quindi il compilatore mostrerà un errore. Così, TypeScript usa un’interfaccia per assicurare la corretta struttura di un oggetto.

Interfaccia come tipo di funzione

L’interfaccia di TypeScript è anche usata per definire il tipo di una funzione. Questo assicura la firma della funzione.

Esempio: Tipo di funzione

Copia

interface KeyValueProcessor{ (key: number, value: string): void;};function addKeyValue(key:number, value:string):void { console.log('addKeyValue: key = ' + key + ', value = ' + value)}function updateKeyValue(key: number, value:string):void { console.log('updateKeyValue: key = '+ key + ', value = ' + value)} let kvp: KeyValueProcessor = addKeyValue;kvp(1, 'Bill'); //Output: addKeyValue: key = 1, value = Bill kvp = updateKeyValue;kvp(2, 'Steve'); //Output: updateKeyValue: key = 2, value = Steve 

Nell’esempio precedente, un’interfaccia KeyValueProcessor include una firma di metodo. Questa definisce il tipo di funzione. Ora, possiamo definire una variabile di tipo KeyValueProcessor che può puntare solo a funzioni con la stessa firma definita nell’interfaccia KeyValueProcessor. Così, la funzione addKeyValue o updateKeyValue è assegnata a kvp. Quindi, kvp può essere chiamato come una funzione.

Tentare di assegnare una funzione con una firma diversa causerà un errore.

function delete(key:number):void { console.log('Key deleted.')} let kvp: KeyValueProcessor = delete; //Compiler Error

ADVERTISEMENT

Interfaccia per il tipo di matrice

Un’interfaccia può anche definire il tipo di una matrice dove è possibile definire il tipo di indice così come i valori: Tipo di matrice Copia

interface NumList { :number}let numArr: NumList = ;numArr;numArr;interface IStringList { :string}let strArr : IStringList;strArr = "TypeScript";strArr = "JavaScript";

Nell’esempio precedente, l’interfaccia NumList definisce un tipo di matrice con indice come numero e valore come tipo numero. Allo stesso modo, IStringList definisce un array di stringhe con indice come stringa e valore come stringa.

Proprietà opzionali

A volte, possiamo dichiarare un’interfaccia con un eccesso di proprietà ma non ci aspettiamo che tutti gli oggetti definiscano tutte le proprietà dell’interfaccia data. Possiamo avere proprietà opzionali, marcate con un “?”. In questi casi, gli oggetti dell’interfaccia possono definire o meno queste proprietà.

Esempio: Optional Property

Copy

interface IEmployee { empCode: number; empName: string; empDept?:string;}let empObj1:IEmployee = { // OK empCode:1, empName:"Steve"}let empObj2:IEmployee = { // OK empCode:1, empName:"Bill", empDept:"IT"}

Nell’esempio precedente, empDept è marcato con ?, quindi gli oggetti di IEmployee possono includere o meno questa proprietà.

Proprietà in sola lettura

TypeScript fornisce un modo per marcare una proprietà come in sola lettura. Questo significa che una volta che ad una proprietà è stato assegnato un valore, non può essere cambiato!

Esempio: Readonly Property

Copy

interface Citizen { name: string; readonly SSN: number;}let personObj: Citizen = { SSN: 110555444, name: 'James Bond' }personObj.name = 'Steve Smith'; // OKpersonObj.SSN = '333666888'; // Compiler Error

Nell’esempio precedente, la proprietà SSN è di sola lettura. Definiamo l’oggetto personObj di tipo Citizen e assegniamo valori alle due proprietà dell’interfaccia. Successivamente, proviamo a cambiare i valori assegnati ad entrambe le proprietàname e SSN. Il compilatore TypeScript mostra un errore quando cerchiamo di cambiare la proprietà SSN di sola lettura.

Extendere le interfacce

Le interfacce possono estendere una o più interfacce. Questo rende la scrittura delle interfacce flessibile e riutilizzabile.

Esempio: Estendere l’interfaccia

Copia

interface IPerson { name: string; gender: string;}interface IEmployee extends IPerson { empCode: number;}let empObj:IEmployee = { empCode:1, name:"Bill", gender:"Male"}

Nell’esempio precedente, l’interfaccia IEmployee estende l’interfaccia IPerson. Quindi, gli oggetti di IEmployee devono includere tutte le proprietà e i metodi dell’interfaccia IPerson altrimenti il compilatore mostrerà un errore.

Implementare un’interfaccia

Similmente a linguaggi come Java e C#, le interfacce in TypeScript possono essere implementate con una classe. La classe che implementa l’interfaccia deve essere strettamente conforme alla struttura dell’interfaccia.

Esempio: Implementazione dell’interfaccia

Copia

interface IEmployee { empCode: number; name: string; getSalary:(number)=>number;}class Employee implements IEmployee { empCode: number; name: string; constructor(code: number, name: string) { this.empCode = code; this.name = name; } getSalary(empCode:number):number { return 20000; }}let emp = new Employee(1, "Steve");

Nell’esempio precedente, l’interfaccia IEmployee è implementata nella classe Employee usando la parola chiave implementazione. La classe implementatrice dovrebbe rigorosamente definire le proprietà e la funzione con lo stesso nome e tipo di dati. Se la classe di implementazione non segue la struttura, allora il compilatore mostrerà un errore.

Certo, la classe implementatrice può definire proprietà e metodi extra, ma almeno deve definire tutti i membri di un’interfaccia.

Nel prossimo capitolo, impareremo di più sulle classi TypeScript.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.