Typwächter sind Mechanismen, die es ermöglichen, den Typ einer Variablen im Codeblock basierend auf bestimmten Prüfungen zu verfeinern (z. B. mit typeof, instanceof oder speziellen Funktionen, die Ausdrücke der Form param is SomeType zurückgeben).
Hauptvorteil – dies ist Sicherheit und Vermeidung von Laufzeitfehlern durch Typüberprüfungen während der Kompilierung.
Beispiel:
interface Fish { swim: () => void } interface Bird { fly: () => void } function isFish(pet: Fish | Bird): pet is Fish { return (pet as Fish).swim !== undefined; } function move(pet: Fish | Bird) { if (isFish(pet)) { pet.swim(); } else { pet.fly(); } }
Hier ist die Funktion isFish ein benutzerdefinierter Typwächter.
Nuancen:
Frage: "Verlässt sich der TypeScript-Compiler immer nur auf den Rückgabewert der Guard-Funktion, oder verwendet er auch eine Analyse innerhalb der Funktion?"
Antwort:
Der TypeScript-Compiler stützt sich nur auf die Signatur des Rückgabewerts param is Type. Was innerhalb der Guard-Funktion passiert, wird nicht auf die Korrektheit der Implementierung analysiert.
Beispiel (gefährlicher Fehler!):
function isString(x: any): x is string { return true; } // Der Compiler wird annehmen, dass es immer ein String ist, obwohl dies nicht der Fall ist: if (isString(123)) { // hier ist x vom Typ string, aber tatsächlich ist es eine Zahl }
Geschichte
In einem Projekt mit geteilten DTO zwischen Frontend und Backend wurde vergessen, eine strenge Überprüfung innerhalb des benutzerdefinierten Type Guards hinzuzufügen. Infolgedessen wurde ein Teil der Daten fälschlicherweise als der erforderliche Typ betrachtet, was zu Abstürzen auf der Client-Seite führte, wenn versucht wurde, auf ein fehlendes Attribut zuzugreifen.
Geschichte
Ein Entwickler schrieb einen Type Guard, der auf ein optionales Feld vertraute, das jedoch in der Datenstruktur möglicherweise gar nicht existierte. In der Folge fehlte im typischen Switch-Case der Zweig, und der Compiler gab keine Warnung aus – zur Laufzeit traten Ausnahmen auf.
Geschichte
In einem der Dienste, beim Übergang zu TypeScript, wurde nur auf die eingebauten Type Guards (typeof, instanceof) vertraut. Bei der Änderung des Prototype von Objekten während der Ausführung wurden die Prüfungen inkorrekt, was zu schwer debugbaren Bugs in der Produktion führte.