I tipi di intersezione (Intersection Types) in TypeScript consentono di creare tipi compositi che combinano le proprietà e i metodi di tutti i tipi di origine. Questo è uno strumento potente per costruire strutture dati flessibili ed estensibili senza l'eccessivo utilizzo dell'ereditarietà delle classi. La costruzione è realizzata utilizzando l'operatore & tra i tipi.
TypeScript fin dalle prime versioni supporta i tipi uniti (|) per esprimere “o”, ma spesso si presenta la necessità di descrivere un oggetto con molteplici proprietà provenienti da diversi interfacce o tipi indipendenti. In questo caso si utilizza l'intersezione (&) — l'oggetto deve soddisfare tutte le interfacce per tutte le proprietà.
Una delle principali difficoltà è il conflitto tra nomi di proprietà identici nei tipi intersecati, la differenza nella loro tipizzazione, così come la correttezza del tipo combinato finale, se si uniscono classi con campi privati o protetti. È anche comune confondere i tipi di intersezione con l'unione (union types), il che porta a errori di compilazione o a problemi nella gestione dell'oggetto.
L'intersezione dei tipi aggrega tutte le proprietà dai tipi uniti, e per ogni proprietà è richiesta la corrispondenza tra entrambi i tipi, se il nome coincide. È utilizzata sia per interfacce che per alias di tipo.
interface A { foo: string; } interface B { bar: number; } type AB = A & B; const item: AB = { foo: "hello", bar: 123 }; // Corretto
Se si intersecano le proprietà con lo stesso nome, il tipo deve corrispondere, altrimenti si verifica un errore:
interface X { val: string; } interface Y { val: number; } // type Z = X & Y; // Errore: incompatibilità di val
Caratteristiche chiave:
& combina tutte le proprietà di entrambi i tipi (interfacce e alias di tipo).Cosa succede se i tipi si intersecano e alcune proprietà hanno tipi incompatibili? (Ad esempio, una proprietà string, un'altra number)
Ci sarà un errore di compilazione, poiché la proprietà non può essere sia string che number contemporaneamente.
È possibile intersecare classi con proprietà private o protette?
È possibile, ma se ci sono tali campi con nomi identici e diversi tipi di accesso, il risultato sarà non valido e TypeScript genererà un errore.
In che modo il tipo di intersezione si differenzia dal tipo di unione (|)?
L'intersezione (A & B) richiede che l'oggetto sia contemporaneamente di entrambi i tipi, mentre l'unione (A | B) richiede che sia almeno uno di essi. Ad esempio:
type U = A | B; // Può essere foo o bar o entrambi type I = A & B; // Deve avere entrambe le proprietà
Un sviluppatore crea un tipo attraverso l'intersezione di più interfacce incoerenti; le proprietà si scontrano, si verificano errori di tipizzazione difficili da risolvere.
Pro: Possibilità di unire rapidamente le capacità di più tipi.
Contro: Il codice non compila o contiene bug impliciti, il debug è difficile.
Separazione delle funzionalità in interfacce indipendenti e combinazione accurata delle stesse attraverso il tipo di intersezione per formare oggetti composite finali.
Pro: Scalabilità, semplicità nei test e nell'estensione, contratto rigoroso.
Contro: Lavoro aggiuntivo per progettare le interfacce e accordarle.