Die Typverengung (Type Narrowing) in TypeScript ist der Prozess, bei dem der Compiler "versteht", dass eine Variable in einem bestimmten Codeabschnitt aufgrund von Bedingungen eindeutig einen konkreteren Typ hat.
Typische Methoden zur Verengung:
typeof:function example(x: number | string) { if (typeof x === 'string') { // x: string hier return x.toUpperCase(); } else { // x: number hier return x.toFixed(2); } }
instanceof (für Klassen):if (dateObj instanceof Date) { // dateObj: Date }
null und undefined:function print(value?: string) { if (value != null) { // value: string console.log(value.length); } }
type Pet = { kind: 'dog'; woof: () => void } | { kind: 'cat'; meow: () => void }; function sound(pet: Pet) { if (pet.kind === 'dog') { pet.woof(); } else { pet.meow(); } }
TypeScript unterstützt auch benutzerdefinierte Prädikatsfunktionen:
function isString(x: unknown): x is string { return typeof x === 'string'; }
Die Verengung macht Typprüfungen sicherer und den Code zuverlässiger.
Kann man die Verengung des Typs durch einfache Vergleiche (z. B.
==/===) garantieren, und funktioniert sie immer?
Antwort: Nein. TypeScript versteht nicht in allen Fällen den Typ aus einfachen Vergleichen, insbesondere wenn der Vergleich zu „vage“ ist oder über indirekte Variablen/Eigenschaften erfolgt. Für Verengungen müssen oft explizite Mechanismen verwendet werden (typeof, instanceof, diskriminierende Eigenschaften und Typwächter).
Beispiel:
function foo(x: number | string | null) { if (x) { // x: string | number, null ist bereits ausgeschlossen, aber eine Verengung auf einen konkreten Typ erfolgt nicht } }
Geschichte
In einem großen TypeScript-Projekt hat die Bedingung user.role == 'admin' den Datentyp nicht verengt, und es mussten dennoch Prüfungen auf die Existenz der Eigenschaft vorgenommen werden. Die Entwickler haben die Regeln der Verengung unterschätzt, was zu Fehlern "Cannot read property ... of undefined" führte.
Geschichte
In einer mobilen Anwendung akzeptierte die Funktion entweder ein Objekt oder einen String. Durch den indirekten Funktionsaufruf, der den Typ änderte, fand keine Verengung statt, und auf bestimmten Geräten stürzte die Anwendung ab, als eine Methode aufgerufen wurde, die beim String fehlte. Die Tests für seltene Fälle sind fehlgeschlagen.
Geschichte
Bei der Migration von JavaScript nach TypeScript wurden keine eigenen Typwächterfunktionen implementiert, mit der Annahme, dass die Überprüfungen auf Eigenschaften den Typ immer verengen würden. Infolgedessen verhielten sich komplexe Objekte mit optionalen Feldern nicht richtig, und zur Laufzeit traten unvorhersehbare Datenzugriffsfehler auf.