TypeScript: Differenze tra Tipi e Interfacce
Ciao ragazzi! Oggi parliamo di un argomento che spesso crea confusione tra chi si avvicina a TypeScript: la differenza tra tipi e interfacce. Vediamo insieme come sfruttarli al meglio nei nostri progetti, con qualche esempio pratico.
Tipi in TypeScript
I tipi in TypeScript sono estremamente flessibili e permettono di rappresentare una vasta gamma di scenari. Vediamo insieme alcuni casi d'uso comuni:
Primitive e Unions:
I tipi possono rappresentare tipi primitivi come
string
,number
,boolean
, ecc. Ma non solo, possiamo anche creare tipi di unione per consentire a una variabile di avere più tipi. Comodo, no?type MyString = string; type MyNumber = number; type MyBoolean = boolean; type Status = 'success' | 'error';
Qui sopra,
Status
può essere solo'success'
o'error'
. Tipo un semaforo, o va tutto bene o c'è un errore!Utility Types:
TypeScript ci offre una serie di utility types predefiniti, come
Partial
,Readonly
eRecord
, che sono davvero utili per manipolare e trasformare i tipi in modo elegante.type PartialPerson = Partial<Person>; type ReadonlyPerson = Readonly<Person>; type RecordOfNumbers = Record<string, number>;
Vuoi rendere tutte le proprietà di un tipo opzionali o renderle solo in lettura? Questi utility types fanno proprio al caso tuo!
Mapped Types:
Con i mapped types possiamo trasformare le proprietà di un tipo esistente in maniera dinamica. Un esempio classico è rendere tutte le proprietà opzionali:
type Optional<T> = { [K in keyof T]?: T[K] };
È come dire a TypeScript: "Prendi tutte le chiavi di
T
e rendile opzionali". Fantastico, no?
Ok, prendiamoci un attimo per vedere un esempio pratico:
Immagina di avere un oggetto User
in TypeScript con delle proprietà obbligatorie:
type User = {
name: string;
age: number;
};
Se provi a creare un oggetto di tipo User
, devi specificare sia name
che age
. Ma se volessi rendere queste proprietà opzionali? Qui entra in gioco il tipo Optional
.
type OptionalUser = Optional<User>;
Ecco cosa succede:
const user1: OptionalUser = {}; // Perfetto, entrambe le proprietà sono opzionali
const user2: OptionalUser = { name: 'Dario' }; // Ok, 'age' è opzionale
const user3: OptionalUser = { age: 32 }; // Ok, 'name' è opzionale
const user4: OptionalUser = { name: 'Dario', age: 32 }; // Va bene, entrambe le proprietà sono presenti
In sostanza, con Optional<T>
tutte le proprietà diventano opzionali, rendendo i tuoi tipi più flessibili e adatti a diverse situazioni.
Interfacce in TypeScript
Passiamo ora alle interfacce. Sono lo strumento perfetto per definire contratti e forme di oggetti, soprattutto quando lavoriamo con le classi.
Unione di Dichiarazioni:
Una caratteristica fantastica delle interfacce è la possibilità di unire dichiarazioni. Puoi definire la stessa interfaccia più volte, e TypeScript le unirà automaticamente.
interface Person { name: string; } interface Person { age: number; } // Ora Person ha sia 'name' che 'age'!
Estendere Altre Interfacce:
Le interfacce possono estendere altre interfacce. Questo promuove il riutilizzo del codice e rende il tuo codice più organizzato e comprensibile.
interface Shape { color: string; } interface Circle extends Shape { radius: number; }
Qui,
Circle
ereditacolor
daShape
, aggiungendo la sua proprietàradius
.Clausola Implements:
Le interfacce sono perfette per definire contratti per le classi. Se una classe implementa un'interfaccia, deve aderire alla sua struttura, punto e basta!
interface Logger { log(message: string): void; } class ConsoleLogger implements Logger { log(message: string) { console.log(message); } }
In questo esempio,
ConsoleLogger
deve implementare il metodolog
, perché lo richiede l'interfacciaLogger
.
Somiglianze tra Tipi e Interfacce
Tipizzazione Strutturale:
Entrambi usano la tipizzazione strutturale. Significa che si basano sulla forma del tipo più che sulla sua dichiarazione esplicita. Basta che la struttura combaci, e TypeScript sarà felice!
Tipi di Intersezione:
Sia tipi che interfacce possono essere combinati con i tipi di intersezione (
&
). Un modo molto potente per creare nuovi tipi che uniscono le caratteristiche di più tipi o interfacce.type Employee = { id: number } & Person;
In questo caso,
Employee
deve avere sia unid
che tutte le proprietà diPerson
.
Conclusione
E quindi, cosa dovresti usare? Tipi o interfacce? Dipende! In generale, le interfacce sono preferibili per definire forme di oggetti e contratti (specialmente con le classi), mentre i tipi sono più flessibili e versatili, adatti per un'ampia gamma di scenari.
TypeScript è in costante evoluzione, quindi tieni d'occhio le ultime novità e sperimenta! L'importante è trovare ciò che funziona meglio per te e per il tuo progetto. Alla prossima, e buon coding! 🚀