Wie man den Typ einer Klasse in TypeScript überprüft: Vom Anfänger zum Profi
\n\nHaben Sie jemals in TypeScript geschrieben, ein Objekt unbekannten Typs erhalten und gedacht: "Und wer bist du eigentlich?"? Diese Frage quält Tausende von Entwicklern – nicht umsonst hat das Thema class type check in TypeScript Hunderttausende von Aufrufen auf Stack Overflow gesammelt. Und heute werden wir ein für alle Mal klären, wie man Klassentypen in TypeScript richtig überprüft.
\n\nIn diesem Artikel erfahren Sie:
\n- \n
- Warum
typeoffür Klassen nicht funktioniert \n - Wie man
instanceofwie ein Schweizer Taschenmesser einsetzt \n - Was type guards sind und wie sie Ihren Code retten \n
- Wie Sie Ihre eigene Typüberprüfung mit
isschreiben \n - Reale Beispiele aus der Praxis \n
Los geht's!
\n\nDas Problem: Warum typeof hier machtlos ist?
\n\nIn JavaScript gibt es den Operator typeof, der hervorragend mit Primitiven funktioniert:
typeof "hello" // "string"\ntypeof 42 // "number"\ntypeof true // "boolean"\n\nAber wenn es um Klassen geht, versagt typeof:
class Dog {}\nclass Cat {}\n\nconst pet = new Dog();\n\ntypeof pet; // "object" — nutzlos!\ntypeof Dog; // "function" — auch nicht das Richtige\n\nWarum? Weil Klassen in JavaScript nur syntaktischer Zucker über Konstruktorfunktionen sind. typeof sieht nur "object" oder "function", unterscheidet aber nicht, welche Klasse es genau ist.
Hier kommt class type check in TypeScript ins Spiel – ein ganzes Arsenal an Werkzeugen, das Ihnen hilft, genau zu bestimmen, mit welcher Klasseninstanz Sie es zu tun haben.
\n\nMethode 1: instanceof – Ihr wichtigster Helfer
\n\nDer direkteste und verständlichste Weg, den Typ einer Klasse zu überprüfen, ist der Operator instanceof. Er prüft, ob die Klasse in der Prototypenkette des Objekts vorhanden ist:
class Animal {\n name: string;\n constructor(name: string) {\n this.name = name;\n }\n}\n\nclass Dog extends Animal {\n bark() {\n console.log("Woof!");\n }\n}\n\nclass Cat extends Animal {\n meow() {\n console.log("Meow!");\n }\n}\n\nfunction handleAnimal(animal: Animal) {\n if (animal instanceof Dog) {\n // TypeScript weiß, dass animal ein Dog ist\n animal.bark();\n } else if (animal instanceof Cat) {\n animal.meow();\n } else {\n console.log(`Unknown animal: ${animal.name}`);\n }\n}\n\nconst rex = new Dog("Rex");\nhandleAnimal(rex); // "Woof!"\n\nBeachten Sie: Nach der Prüfung animal instanceof Dog verengt TypeScript automatisch den Typ (type narrowing) und erlaubt es, Methoden von Dog fehlerfrei aufzurufen. Das ist die Magie der type guards – eingebauter Typbeschützer.
Wann funktioniert instanceof nicht?
\n- \n
- Bei der Arbeit mit verschiedenen Fenstern/Frames (unterschiedliche globale Objekte) \n
- Wenn Klassen in verschiedenen Modulen mit unterschiedlichen Versionen definiert sind \n
- Bei der Überprüfung von Interfaces (sie existieren zur Laufzeit nicht) \n
Methode 2: Eigene type guards mit dem Operator is
\n\nManchmal reicht instanceof nicht aus. Zum Beispiel, wenn Sie nicht nur die Klasse, sondern auch zusätzliche Bedingungen prüfen möchten. Hier helfen benutzerdefinierte type guards mit dem Schlüsselwort is:
interface Bird {\n fly(): void;\n layEggs(): void;\n}\n\ninterface Fish {\n swim(): void;\n layEggs(): void;\n}\n\nfunction isFish(pet: Bird | Fish): pet is Fish {\n return (pet as Fish).swim !== undefined;\n}\n\nfunction move(pet: Bird | Fish) {\n if (isFish(pet)) {\n // TypeScript weiß: pet ist ein Fish\n pet.swim();\n } else {\n pet.fly();\n }\n}\n\nBeachten Sie die Syntax: pet is Fish im Rückgabetyp. Das sagt TypeScript: "Wenn diese Funktion true zurückgibt, dann ist der Parameter pet ein Fish". Jetzt wird TypeScript den Typ überall dort verengen, wo Sie es verwenden.