Exclude<T, U> ist ein Utility-Typ, der in TypeScript eingeführt wurde, um einen Typ von einem anderen abzuziehen, wenn bestimmte Werte aus einem Union-Typ ausgeschlossen werden müssen.
Ursprünglich gab es in TypeScript keinen bequemen Weg, einen Typ von einem anderen abzuziehen. Bei der Erstellung von generischen APIs und auch beim Refactoring war es häufig erforderlich, einen "Rest-Typ" zu erhalten – alles außer den verbotenen Werten. Anstatt manuelle Manipulationen mit Union durchzuführen, mussten mehrere ähnliche Interfaces unterstützt werden.
Zum Beispiel, wenn es einen Typ 'A | B | C' gibt, aber man den Typ ohne B erhalten möchte. Dies ist häufig erforderlich, wenn komplexe Eingabeparameter für Funktionen erstellt, erlaubte Werte gefiltert und dynamisch Typen gebildet werden.
Exclude löst dieses Problem. Seine vereinfachte Signatur lautet:
type Exclude<T, U> = T extends U ? never : T;
Er gibt einen Typ zurück, der alle Mitglieder von U aus T ausschließt.
Beispiel:
type Status = 'draft' | 'published' | 'removed'; type UserVisibleStatus = Exclude<Status, 'removed'>; const visible: UserVisibleStatus = 'draft'; // OK
Wichtige Merkmale:
Kann man Exclude auch für einfache Typen und nicht für Union verwenden?
Wenn T kein Union-Typ ist, aber in U enthalten ist – funktioniert Exclude trotzdem, aber das Ergebnis könnte never oder T sein, was nicht immer intuitiv ist.
Exclude<'a', 'a'> // Ergebnis: never Exclude<'a', 'b'> // Ergebnis: 'a'
Entfernt Exclude alle Erwähnungen des Typs in der Objektstruktur?
Nein, Exclude geht nicht rekursiv durch verschachtelte Felder des Typs und schließt nur auf der obersten Ebene der Union aus.
Wie funktioniert Exclude mit Interfaces und Objekt-Typen?
Er vergleicht den gesamten Typ, nicht einzelne Eigenschaften. Daher entfernt Exclude aus einer Union mehrerer Interfaces nur die, die vollständig mit U übereinstimmen.
interface A { x: number }; interface B { y: string }; // Exclude<A|B, B> ergibt: A (B stimmt vollständig überein)
Validierung der Benutzerrollen durch Exclude<UserRoles, 'admin'>, aber vergessen, dass Exclude nicht auf verschachtelte Strukturen angewendet wird – die Berechtigungen 'admin:sub' wurden nicht ausgeschlossen.
Vorteile:
Nachteile:
Verwendung von Exclude zur Einschränkung der öffentlichen API durch die Aktionen: Exclude<Action, 'delete'>, was die gefährliche Operation ausschließt.
Vorteile:
Nachteile: