Exclude<T, U> è un tipo utilitario introdotto in TypeScript per sottrarre un tipo da un altro, quando è necessario escludere alcuni valori da un tipo union.
Inizialmente in TypeScript non c'era un modo comodo per sottrarre un tipo da un altro. Nella creazione di API generiche, così come durante il refactoring, era spesso necessario ottenere un tipo "residuo" — tutto tranne i valori vietati. Piuttosto che eseguire manualmente le manipolazioni con union, era necessario mantenere più interfacce simili.
Ad esempio, quando si ha un tipo 'A | B | C', ma si desidera ottenere un tipo senza B. Questo è spesso necessario nella costruzione di parametri di ingresso complessi per le funzioni, nella filtrazione dei valori consentiti e nella formazione dinamica dei tipi.
Exclude risolve questo problema. La sua firma semplificata è la seguente:
type Exclude<T, U> = T extends U ? never : T;
Restituisce un tipo che esclude da T tutti i membri di U.
Esempio:
type Status = 'draft' | 'published' | 'removed'; type UserVisibleStatus = Exclude<Status, 'removed'>; const visible: UserVisibleStatus = 'draft'; // OK
Caratteristiche chiave:
Si può usare Exclude per tipi normali, e non union?
Se T non è un tipo union, ma è incluso in U — Exclude funzionerà comunque, ma il risultato potrebbe essere never o T, il che non è sempre intuitivo.
Exclude<'a', 'a'> // risultato: never Exclude<'a', 'b'> // risultato: 'a'
Rimuove Exclude tutte le menzioni di un tipo nella struttura dell'oggetto?
No, Exclude non passa ricorsivamente attraverso i campi nidificati del tipo, esclude solo al livello superiore dell'union.
Come funziona Exclude con interfacce e tipi-oggetto?
Confronta l'intero tipo, non le singole proprietà. Pertanto, Exclude da un union di diverse interfacce rimuove solo quelle che corrispondono completamente a U.
interface A { x: number }; interface B { y: string }; // Exclude<A|B, B> restituisce: A (B corrisponde completamente)
Validazione dei ruoli utente tramite Exclude<UserRoles, 'admin'>, ma si è dimenticato che Exclude non si applica alle strutture nidificate — i diritti 'admin:sub' non erano stati esclusi.
Pro:
Contro:
Utilizzo di Exclude per limitare l'API pubblica sulle azioni: Exclude<Action, 'delete'>, che esclude l'operazione pericolosa.
Pro:
Contro: