Was ist Typinferenz?
Type Inference
Typinferenz ist die Fähigkeit eines Compilers, den Typ eines Ausdrucks aus dem Zusammenhang zu erschließen, statt ihn im Quelltext ausdrücklich genannt zu bekommen. In TypeScript schreibst du dadurch deutlich weniger Annotationen und bekommst trotzdem dieselbe Prüfung beim Kompilieren.
Du schreibst in TypeScript selten einen Typ hin und bekommst trotzdem schon beim Tippen angezeigt, dass ein Feld fehlt. Dahinter steckt die Ableitung durch den Compiler.
KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
- Findet sich in
- TypeScript, C# mit var, C++ mit auto, Rust
- Leitet ab aus
- Zuweisung, Rückgabewert und Aufrufkontext
- Grenze
- Daten aus JSON kommen als beliebiger Typ herein
- Verwechselt mit
- Dynamischer Typisierung
Woher der Compiler den Typ nimmt
Die einfachste Quelle ist die Zuweisung. Bei let preis = 19.9 steht fest, dass eine Zahl gemeint ist, und jede spätere Zuweisung eines Textes meldet einen Fehler. Dabei macht die Art der Deklaration einen Unterschied: let name = 'Anna' bekommt den Typ string, const name = 'Anna' dagegen den Literaltyp 'Anna', weil sich der Wert nicht mehr ändern kann.
Die zweite Quelle ist der Rumpf einer Funktion, aus dem TypeScript den Rückgabetyp berechnet. Die dritte ist der Kontext der Verwendung. Übergibst du eine Pfeilfunktion an array.map, kennt der Compiler die erwartete Signatur des Callbacks und leitet daraus den Typ des Parameters ab. Genau deshalb musst du bei Callbacks fast nie etwas annotieren.
Bei Generics arbeitet die Ableitung über die Argumente. Eine Funktion mit der Signatur ersteElement<T>(liste: T[]): T bestimmt T beim Aufruf aus dem übergebenen Array, sodass ersteElement(namen) ohne spitze Klammern auskommt und trotzdem den richtigen Typ zurückgibt.
Wann du trotzdem annotierst
Drei Stellen lohnen die ausdrückliche Angabe. Die erste sind öffentliche Schnittstellen: Wird der Rückgabetyp einer exportierten Funktion nur abgeleitet, ändert sich die Schnittstelle stillschweigend mit, sobald jemand den Rumpf umbaut, und der Fehler taucht erst bei den Aufrufern auf. Eine Annotation meldet ihn dort, wo er entsteht.
Die zweite Stelle sind leere Sammlungen. const eintraege = [] gilt als any[], solange TypeScript den Inhalt nicht aus späteren push-Aufrufen erschließen kann, während const eintraege: Buchung[] = [] von Anfang an festhält, was hineingehört. Die dritte sind Werte von außen. Was aus JSON.parse oder aus einer Netzwerkantwort kommt, kennt der Compiler nicht, hier legst du selbst fest, womit du rechnest, am besten zusammen mit einer Prüfung zur Laufzeit.
Wo die Ableitung in die Irre führt
Der häufigste Ärger entsteht durch zu breite Ableitung. Ein Objektliteral, das du in einer Variablen zwischenspeicherst, bekommt für ein Feld mit dem Wert 'GET' den Typ string und nicht den Literaltyp 'GET'. Erwartet die aufgerufene Funktion eine Union aus 'GET' und 'POST', schlägt die Übergabe fehl, obwohl der Wert stimmt. Abhilfe schaffen der Zusatz as const am Literal oder eine Annotation der Variablen mit dem erwarteten Typ.
In die andere Richtung kann die Ableitung Fehler verdecken. Fließt irgendwo any hinein, etwa aus einer Bibliothek ohne Typdefinitionen, wandert dieser Typ durch die ganze Aufrufkette und macht alles Folgende ungeprüft, ohne dass eine Warnung erscheint. Die Compileroption noImplicitAny fängt nur den impliziten Fall ab, ein ausdrücklich deklariertes any aus einer fremden Deklaration bleibt unsichtbar.
KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Typinferenz und was oft damit gleichgesetzt wird
Die Annotation schreibt den Typ vor, die Inferenz liest ihn ab. Beide führen zur gleichen Prüfung, aber eine Annotation ist zusätzlich eine Zusicherung: Weicht der Rumpf davon ab, meldet der Compiler den Fehler an der Funktion selbst.
Mit as behauptest du gegenüber dem Compiler einen Typ, ohne dass er geprüft wird. Das ist keine Ableitung, sondern deren Abschaltung an dieser Stelle, und einer der häufigsten Gründe für Laufzeitfehler in typisiertem Code.
TypeScript vergleicht Typen anhand ihres Aufbaus und nicht anhand ihres Namens. Das ist unabhängig von der Inferenz, wird mit ihr aber oft verwechselt, weil beides dazu führt, dass man selten Typnamen hinschreiben muss.
KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Die Ableitung endet an der Systemgrenze
Innerhalb deines Codes zieht der Compiler die Typen sauber durch. In dem Moment, in dem eine Antwort aus dem Netz oder ein Wert aus einer Datenbank hereinkommt, hat er keine Grundlage mehr und arbeitet mit einem beliebigen Typ weiter. Ab dieser Stelle glaubt er alles, was du behauptest, und der Fehler fällt erst zur Laufzeit auf. Deshalb gehört an jede Systemgrenze eine echte Prüfung der Daten.
Verschärft wird das durch die Zusicherung mit as. Damit sagst du dem Compiler, er solle das Nachfragen einstellen, ohne dass irgendetwas geprüft wird. Wo im Team viele solcher Zusicherungen stehen, ist die Typprüfung faktisch abgeschaltet, obwohl der Build grün bleibt.
In die andere Richtung leitet der Compiler manchmal zu großzügig ab. Ein Wert, den du in einer veränderbaren Variablen ablegst, gilt danach als allgemeine Zeichenkette und nicht mehr als eine der drei erlaubten Bezeichnungen. Dass diese Verallgemeinerung passiert, sieht man dem Code nicht an, deshalb lohnt sich bei Aufzählungen die ausdrückliche Angabe.
Typinferenz lernen
Wie weit du die Ableitung treiben kannst und wo eine Annotation die Schnittstelle stabil hält, zeigen die TypeScript-Trainings für Entwicklerteams an durchgehenden Beispielprojekten.
Typen fangen nur Formfehler ab, das Verhalten prüfst du weiterhin mit Tests, wie sie die Kurse rund um automatisierte Tests behandeln.
Kurse, die Typinferenz behandeln
Häufige Fragen
Verlangsamt Typinferenz den Build?
Soll ich Rückgabetypen immer hinschreiben?
Was ist der Unterschied zwischen any und unknown bei abgeleiteten Typen?
Deine Ansprechpartner
Du willst das Thema nicht nur nachschlagen, sondern anwenden können? Wir beraten dich persönlich und kostenlos.
Yves Hoppe
Weiterbildung & Beratung
Ordnet mit dir ein, welcher Kurs zu deinem Vorwissen passt.
Norbert Jansen
Beratung & Inhouse
Plant Inhouse-Trainings, die an euren eigenen Daten und Abläufen ansetzen.
Typinferenz im Kurs statt im Lexikon
Nachschlagen bringt dich bis zum Verstehen. Anwenden lernst du an echten Aufgaben.