Start / Seminare / Modern TypeScript 7
Modul
Union Types und Control Flow Analysis
9 Kapitel in diesem Modul-Video · Laufzeit
Transkript
Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.
Union Types und Control Flow Analysis
0:00 Dies ist das inhaltliche Herzstück des ersten Tages. Wir haben bisher einzelne Werte beschrieben — jetzt beschreiben wir Alternativen und Abläufe. Und damit kommen wir zu dem, was ein Typsystem wirklich wertvoll macht: Es geht nicht darum, richtige Zustände zu erlauben, sondern darum, falsche gar nicht erst hinschreibbar zu machen.
0:19 Alles, was wir in diesem Modul bauen, begegnet uns später wieder: in Modul 6 als validierte Grenze, in Modul 14 als Erweiterung. Nehmen Sie sich für dieses Modul etwas mehr Aufmerksamkeit — es zahlt sich über die restlichen zwei Tage aus.
Union Types und Control Flow Analysis
0:34 Der Leitsatz steht gleich oben und ist bewusst zugespitzt: Unmögliche Zustände nicht darstellbar zu machen, ist der wirksamste Einsatz eines Typsystems. Nicht „zu prüfen" — „nicht darstellbar zu machen". Der Unterschied ist groß. Eine Prüfung kann man vergessen; was sich nicht hinschreiben lässt, entsteht gar nicht erst.
0:52 Wir gehen den Weg dorthin in acht Schritten, von den beiden Grundoperatoren über die Verengung im Kontrollfluss bis zu Zustandsmodellen und Ergebnistypen — und bauen am Ende einen ganzen Geschäftsprozess.
Union und Intersection Types
1:05 Zwei Operatoren, die im Code sehr ähnlich aussehen und fachlich gegensätzliche Dinge behaupten. Der eine sagt: eines von mehreren. Der andere: alles zugleich. Und einer der beiden wird im Alltag deutlich häufiger geschrieben, als er gebraucht wird. Eine Union sagt: eines von mehreren. Eine Intersection sagt: alles gleichzeitig.
1:26 Ein Bild aus dem Alltag: Auf der Speisekarte steht „Suppe oder Salat" — das ist eine Union, Sie bekommen genau eines. „Menü mit Suppe und Salat" ist eine Intersection. Nun ist die entscheidende Beobachtung: Fachliche Modelle brauchen die Union viel häufiger. Software scheitert an Alternativen, nicht an Kombinationen — daran, dass ein Fall vergessen wurde, nicht daran, dass zwei Eigenschaften zusammenkommen.
1:51 Deshalb ist die Union das Arbeitspferd der Modellierung, und die Intersection wird häufiger geschrieben, als sie gebraucht wird. Oben eine Kennung, die entweder eine Auftrags- oder eine Kundennummer ist — nie beides. Unten ein Auftrag, der zusätzlich einen Änderungszeitpunkt trägt: die Kombination zweier Beschreibungen zu einer.
2:12 Achten Sie auf die Fußzeile, dort steht ein Detail mit praktischen Folgen: Die Reihenfolge der Glieder einer Union war nie zugesichert, und TypeScript 7 ordnet sie tatsächlich anders als Version 6. Wenn irgendwo in Ihrem Projekt diese Reihenfolge in einer Fehlermeldung oder einem festgehaltenen Testergebnis auftaucht, wird die Umstellung dort rot.
2:32 Kein Fehler des Compilers — eine Annahme, die nie galt. Vier Prüffragen, und die letzte ist die praktischste. Schließen sich die Fälle gegenseitig aus? Dann Union. Sollen Eigenschaften zusammengelegt werden? Dann Intersection. Ergibt die Kombination fachlich gar keinen Sinn — etwa ein Auftrag, der gleichzeitig offen und abgeschlossen ist?
2:54 Dann war es nie eine Intersection, sondern eine Union, die man falsch geschrieben hat. Und im Zweifel: Union. Sie zwingt Sie zur Fallunterscheidung, und genau das ist erwünscht. Die Intersection erlaubt Ihnen, die Unterscheidung zu umgehen — und das ist selten ein Gewinn. Der erste Punkt ist gerade jetzt aktuell: sich auf die Reihenfolge der Glieder verlassen, etwa in festgehaltenen Testergebnissen.
3:19 Diese Reihenfolge war nie zugesichert, und mit dem neuen Compiler ändert sie sich. Der zweite ist eine stille Falle: Intersections aus Typen bilden, die einander widersprechen — das Ergebnis ist ein Typ ohne jeden möglichen Wert, und der Compiler sagt dazu erst etwas, wenn Sie ihn zu benutzen versuchen. Und der dritte führt uns zum nächsten Kapitel: Unions ohne Unterscheidungsfeld bauen und danach mit Behauptungen arbeiten. Wir sehen gleich, wie es besser geht.
Type Narrowing im Kontrollfluss
3:46 Jetzt zu einer Fähigkeit, die viele täglich nutzen, ohne sie je bewusst wahrzunehmen: Der Compiler liest Ihre Bedingungen mit. Er weiß nach einem if-Block mehr als davor. Wer diese Mechanik versteht, schreibt Bedingungen so, dass der Compiler mitdenkt — statt gegen ihn mit Zusicherungen zu arbeiten. TypeScript verfolgt den Kontrollfluss durch eine Funktion und verengt den Typ einer Variablen entlang der Prüfungen, die im Code stehen.
4:12 Stellen Sie sich einen Ermittler vor, der mit einer Liste von Verdächtigen beginnt und nach jeder beantworteten Frage einige streicht. Am Ende bleibt genau einer übrig. Genau so arbeitet der Compiler. Wichtig ist die Einordnung: Das ist keine Zusatzfunktion für Fortgeschrittene, das ist die Grundmechanik. Fast jede sinnvolle Arbeit mit Unions besteht darin, sie zu verengen — der Rest ergibt sich daraus.
4:36 Interessant ist hier wieder die rechte Spalte, denn jede Prüfung hat eine Grenze. Die Prüfung auf den Grundtyp kennt keine Objektformen — sie sagt Ihnen „Objekt" und ist damit fertig. Die Prüfung auf eine Klasse scheitert über Realm-Grenzen hinweg, etwa zwischen zwei Fenstern oder Modulinstanzen; ein seltener, aber sehr verwirrender Fehler.
4:56 Die Prüfung auf das Vorhandensein einer Eigenschaft sagt nur, dass das Feld da ist, nichts über seinen Typ. Und der Vergleich auf ein Literal ist die schärfste — er braucht aber ein Unterscheidungsfeld. Genau darauf laufen wir in Kapitel 4 zu. Eine kleine Funktion, drei mögliche Eingangstypen. Nach der ersten Prüfung ist der Text abgehandelt, nach der zweiten das Datum.
5:18 Und jetzt die schönste Zeile des Beispiels: die letzte. Dort steht keine Prüfung mehr, und trotzdem können Sie mit der Zahl arbeiten — der Compiler hat die beiden anderen Fälle bereits ausgeschlossen und weiß, dass nur noch einer übrig sein kann. Diese Art zu schreiben nennt man auch Frühabbruch: einen Fall klären, verlassen, nächster Fall. Sie führt zu Code, in dem der Compiler mit jedem Schritt mehr weiß statt weniger.
5:43 Drei Situationen, in denen die Verengung verlorengeht — und alle drei erzeugen Fehlermeldungen, die zunächst unverständlich wirken. Erstens: eine Zwischenvariable, deren Zusammenhang der Compiler nicht verfolgt; die Prüfung gilt dann für die eine Variable, der Zugriff geschieht über die andere. Zweitens der Klassiker, der bis heute trägt: Die Grundtypprüfung meldet für den leeren Wert „Objekt" — ein Fehler aus den Anfangstagen von JavaScript, den niemand mehr reparieren kann.
6:10 Und drittens: Nach einem Warten auf ein Ergebnis oder in einem Rückruf ist die Verengung nicht mehr gültig, weil dazwischen etwas passiert sein könnte.
Benutzerdefinierte Type Guards
6:19 Manchmal reichen die eingebauten Prüfungen nicht, und Sie beschreiben selbst, woran ein Typ zu erkennen ist. Das ist mächtig — und es hat einen Haken, den man kennen muss, bevor man es einsetzt: Der Compiler glaubt Ihnen dabei ungeprüft. Sie schreiben eine Funktion, die als Ergebnis nicht nur „wahr oder falsch" zurückgibt, sondern zugleich behauptet: Wenn ich wahr sage, dann ist dieser Wert von jenem Typ.
6:43 Der Compiler übernimmt diese Aussage — ohne sie nachzuprüfen. Das Bild dazu: Sie unterschreiben ein Gutachten. Ab da verlässt sich jeder darauf, und niemand schaut noch einmal hin. Ein falsch geschriebenes Prädikat belügt deshalb nicht nur sich selbst, sondern jede folgende Zeile Code. Wer so etwas schreibt, übernimmt Verantwortung — das ist der wichtigste Satz dieses Kapitels.
7:06 Oben die ausgeschriebene Form mit der Behauptung in der Signatur. Unten etwas, das viele noch nicht kennen: Seit Version 5.5 leitet der Compiler solche Prädikate oft selbst ab. Wenn eine Funktion direkt einen Vergleich zurückgibt — wie hier beim Filtern —, versteht er, dass danach nur noch offene Aufträge übrig sind, ganz ohne Zutun.
7:26 Das heißt: Viele der Prädikate, die heute in Projekten stehen, sind schlicht überflüssig geworden. Die Einschränkung steht in der Fußzeile: Es greift nur bei direkter Rückgabe eines Vergleichs. Sobald eine Zwischenvariable dazwischenkommt, ist es vorbei. Drei gute Gründe und ein schlechter. Gerechtfertigt ist ein eigenes Prädikat, wenn die Erkennung mehrere Bedingungen oder eine Hilfsfunktion braucht — dann leistet es echte Arbeit.
7:52 Wenn dieselbe Prüfung an vielen Stellen gebraucht wird — dann spart es Wiederholung. Und wenn die Prüfung fachlich einen Namen verdient, statt überall ausgeschrieben zu stehen. Nicht gerechtfertigt ist es als Abkürzung, um eine Fehlermeldung loszuwerden. Genau dieser Einsatz ist leider der häufigste — und er verwandelt ein Prüfwerkzeug in eine höflich formulierte Behauptung.
8:15 Der erste Punkt ist der gefährlichste im ganzen Modul: ein Prädikat, das die Bedingung nur unvollständig prüft. Es sieht aus wie eine Prüfung, wird wie eine Prüfung behandelt und ist keine. Der zweite ist die Steigerung davon: solche Prädikate für Daten von außen einsetzen, ohne die Felder wirklich zu prüfen — damit haben Sie sich eine ungeprüfte Grenze gebaut, die im Review sogar sauber aussieht.
8:37 In Modul 6 lernen wir, wie man das richtig macht. Und der dritte erinnert an die Einschränkung von eben: Bei Zwischenvariablen greift die Ableitung nicht mehr.
Discriminated Unions
8:47 Jetzt kommt das Muster, um das sich das halbe Seminar dreht. Ein einziges Feld verwandelt eine gewöhnliche Union in ein belastbares Modell — und ab hier begleitet uns der Reparaturauftrag der Firma Kurbelwerk. Er kommt in Modul 6, in Modul 13 und in Modul 14 wieder. Die Idee ist verblüffend einfach: Alle Glieder der Union tragen dasselbe Feld, jedes mit einem eigenen festen Wert. Dieses Feld ist der Ausweis.
9:13 Zeigt man ihn vor, weiß der Compiler sofort, in welchem Fall er sich befindet — und damit auch, welche weiteren Felder existieren und welche nicht. Und dieses „welche nicht" ist der eigentliche Gewinn. Genau daran zeigt sich der Unterschied zu einem Objekt mit lauter optionalen Feldern: Dort ist alles vielleicht da. Hier ist in jedem Fall genau geregelt, was da ist.
9:36 Vier Zustände eines Reparaturauftrags, und sehen Sie sich an, wie die Felder verteilt sind. Ein angenommener Auftrag hat eine Nummer, aber keinen Betrag — und zwar nicht „einen leeren Betrag", sondern gar keinen. Der Betrag entsteht erst mit dem Voranschlag und existiert vorher fachlich nicht. Nach der Abholung gibt es dafür eine Belegnummer.
9:56 Das ist der ganze Gewinn, und er steht in der Fußzeile: nicht undefined, sondern gar nicht. Vergleichen Sie das mit dem üblichen Objekt, in dem alle Felder optional sind — dort müssten Sie an jeder Stelle raten, welche Kombination gerade gültig ist. Vier Wirkungen, und die letzte ist die unterschätzte. Ein Zugriff auf den Betrag im Zustand „angenommen" wird zum Übersetzungsfehler — nicht zu einer leeren Anzeige irgendwo im Betrieb.
10:22 Kein Feld muss optional sein, nur weil es nicht in jedem Fall vorkommt. Jeder Zweig kennt genau seine Felder, ohne dass Sie im Rumpf nachfragen müssen. Und dann das Vierte: Das Modell dokumentiert den Geschäftsprozess, ohne dass jemand ihn aufschreiben musste. Wer diese vier Zeilen liest, versteht den Ablauf der Werkstatt.
10:41 Das schafft kein Kommentar, und es veraltet auch nicht. Der erste Punkt ist der, an dem die Übung am Ende dieses Moduls scheitert, wenn sie scheitert: das Unterscheidungsfeld als allgemeine Zeichenkette typisieren statt als feste Auswahl. Dann sieht das Modell richtig aus und verengt gar nichts — der Compiler kann die Fälle nicht auseinanderhalten.
11:02 Der zweite: mehrere Unterscheidungsfelder einführen; damit verlieren Sie die Verengung, weil der Compiler nicht weiß, welches führt. Und der dritte: Felder vorsichtshalber in alle Glieder kopieren, die nur in einem gebraucht werden. Dann sind Sie wieder beim Objekt mit optionalen Feldern angekommen.
Exhaustiveness Checks mit never
11:19 Und nun die Kür, die zugleich das beste Argument für Typsysteme überhaupt ist. Wir sorgen dafür, dass ein neuer Fall im Modell den Build bricht — und zwar an jeder Stelle, die ihn behandeln müsste. Nicht den Betrieb. Den Build. Der Typ never ist der Typ, der keinen einzigen möglichen Wert hat. Klingt nutzlos, ist aber genial einsetzbar.
11:40 Der Trick: An der Stelle im Code, die unerreichbar sein sollte, weil alle Fälle behandelt sind, übergeben Sie die Variable an eine Funktion, die genau diesen Typ erwartet. Solange alles abgedeckt ist, passt das. Kommt ein Fall hinzu, ist die Variable dort plötzlich nicht mehr leer — und der Compiler meldet sich. Ein Bild: eine Waage, die genau dann kippt, wenn irgendwo ein Gewicht dazugekommen ist, das niemand eingerechnet hat.
12:06 Vier Fälle, jeder mit seinem Text, und ganz unten der Zweig, der niemals erreicht werden darf. Die kleine Hilfsfunktion darunter ist der ganze Mechanismus — eine Zeile. Und jetzt stellen Sie sich vor, morgen kommt ein fünfter Zustand ins Modell, sagen wir „storniert". Ohne diese letzte Zeile bliebe der neue Zustand still: Die Funktion gäbe schlicht nichts zurück, die Oberfläche zeigte eine Lücke, und niemand merkte etwas.
12:31 Mit dieser Zeile bricht der Build, und zwar an jeder Auswertung im ganzen Projekt. Sie bekommen eine vollständige Arbeitsliste geschenkt. Vier Gründe, und ich meine die Überschrift ernst. Es findet alle betroffenen Stellen, nicht nur die, an die jemand beim Testschreiben gedacht hat. Es wirkt beim Übersetzen, nicht erst beim Ausführen — Sie brauchen keinen Testlauf, um es zu erfahren. Es kostet eine Zeile pro Auswertung und keinen Testaufbau.
12:59 Und deshalb der letzte Punkt: Wenn Sie jemand fragt, was ein Typsystem praktisch bringt, ist das die Antwort. Nicht die Autovervollständigung im Editor — die Gewissheit, beim nächsten Umbau alle Stellen zu finden.
Null und Fehler unter strict
13:12 Jetzt zu einem Thema, das viele als lästig empfinden — und das genau deshalb funktioniert. Unter strenger Prüfung sind der leere Wert und das Fehlen eines Werts eigene Fälle, die behandelt werden müssen. Das ist unbequem, und das ist der Zweck. Seit Version 6.0 ist die strenge Prüfung voreingestellt, und damit auch die Trennung von leeren Werten. Sie müssen behandelt werden, bevor Sie auf einen Wert zugreifen dürfen.
13:37 Das erzeugt Arbeit — aber an genau den Stellen, an denen sie fachlich hingehört. Denn die Frage „Was, wenn nichts gefunden wird?" ist keine technische Formalie, sondern eine fachliche Entscheidung, die irgendwer irgendwann treffen muss. Ohne diese Prüfung trifft sie niemand, und die Anwendung entscheidet sich an einer zufälligen Stelle für einen Absturz.
13:58 Die Suche liefert einen Auftrag — oder eben nichts. Der Compiler zwingt Sie, diesen zweiten Fall zu klären, bevor Sie weitermachen dürfen. Beachten Sie, wie sich das liest: Der Nicht-gefunden-Fall steht ausdrücklich im Code, mit einer eigenen Antwort, und wer die Funktion später liest, sieht sofort, wie sie sich dann verhält.
14:17 Ohne strenge Prüfung wäre diese Behandlung optional gewesen — und optionale Fehlerbehandlung ist erfahrungsgemäß keine. Der Zugriff vor der Prüfung ist jetzt ein Übersetzungsfehler statt einer Ausnahme im Betrieb. Genau diese Verschiebung ist der ganze Gewinn. Alle drei Punkte sind Wege, die neu gewonnene Unbequemlichkeit wieder loszuwerden.
14:37 Den Nicht-gefunden-Fall mit dem Ausrufezeichen wegdrücken, statt ihn zu behandeln — damit versprechen Sie dem Compiler etwas, das Sie nicht wissen. Leere Werte und fehlende Werte im selben Modell mischen, ohne die Bedeutungen zu trennen — dann weiß später niemand, was welches heißt. Und der subtilste: die sichere Zugriffskette überall streuen.
14:57 Dann läuft nichts mehr auf einen Fehler, sondern alles ins Leere — und der Fehlerfall wird unsichtbar, statt behandelt zu sein.
Zustände statt boolescher Schalter
15:05 Jetzt ein Muster, das Sie in fast jedem gewachsenen Projekt finden — und das sich mit dem, was wir gerade gelernt haben, auflösen lässt. Die Überschrift sagt schon alles: Drei Schalter erlauben acht Kombinationen. Gültig sind meistens drei. Boolesche Felder addieren sich nicht, sie multiplizieren sich. Drei unabhängige Schalter beschreiben acht Kombinationen; bei vier sind es schon sechzehn.
15:28 Fachlich existieren davon meist nur eine Handvoll — der Rest sind Zustände, die es gar nicht geben darf, aber jederzeit entstehen können. Ein Zustandstyp beschreibt genau die gültigen. Alles andere ist nicht etwa verboten, es ist schlicht nicht hinschreibbar. Ein Bild: eine Fernbedienung mit acht Schalterkombinationen, von denen fünf das Gerät in einen undefinierten Zustand versetzen — gegenüber einem Drehknopf mit drei beschrifteten Stellungen.
15:55 Vier Zeilen, und die dritte zeigt, warum das Problem mit der Zeit größer wird statt kleiner. Ein neuer fachlicher Fall bedeutet bei Schaltern einen weiteren Schalter — und damit eine Verdopplung der Kombinationen, von acht auf sechzehn. Beim Zustandstyp ist es ein weiteres Glied in der Union, und der Vollständigkeitscheck aus Kapitel 5 zeigt Ihnen sofort, wo Sie ihn behandeln müssen.
16:17 Die letzte Zeile betrifft die Menschen: Beim Review von Schaltern müssen Sie Kombinationen im Kopf durchspielen. Beim Zustandstyp lesen Sie den Namen. Das ist ein Unterschied in der Ermüdung, und Ermüdung erzeugt Fehler. Vier Spürnasen für Ihren eigenen Code. Zwei Schalter, die nie gleichzeitig wahr sein dürfen — das ist ein Zustand, der als zwei Felder verkleidet ist.
16:39 Ein Feld, das nur bei bestimmten Schalterständen gilt — das ist ein Zustandsfeld. Kommentare wie „nur gesetzt, wenn …" sind der sicherste Hinweis überhaupt; dort hat jemand ein Modell in Prosa aufgeschrieben, weil der Typ es nicht ausdrücken konnte. Und Prüfungen, die dieselbe Kombination an fünf Stellen wiederholen. Wenn Sie eines davon finden, haben Sie Ihren Kandidaten für den Umbau.
Result-orientierte Rückgabemodelle
17:04 Zum letzten Baustein dieses Moduls: Fehler als Wert statt als Sprung. Und gleich vorweg — das ist kein Dogma. Die Frage im Seminar lautet nicht, ob Ausnahmen böse sind. Sie lautet: Welcher Fehler ist fachlich erwartbar, und welcher nicht? Statt eine Ausnahme zu werfen, kann eine Funktion Erfolg oder Misserfolg als Wert zurückgeben — technisch genau die unterscheidbare Union, die wir vorhin gebaut haben, nur mit einem Erfolgsmerkmal als Ausweis.
17:32 Der praktische Effekt: Der Aufrufer kommt an das Ergebnis nur heran, wenn er den Fehlerfall zuvor behandelt hat. Der Unterschied zur Ausnahme ist die Sichtbarkeit. Eine Ausnahme sieht man der Signatur nicht an, sie springt an einer Stelle heraus, die man nicht liest. Ein Ergebniswert steht im Vertrag. Sehen Sie sich die letzte Zeile an: Die Verbuchung ist überhaupt nur erreichbar, wenn die Prüfung vorher stattgefunden hat.
17:57 Der Compiler lässt Sie gar nicht an den Wert heran, bevor Sie den Fehlerfall abgehandelt haben. Die Fußzeile bringt die Einschränkung auf den Punkt, und die ist mir wichtig: Vergessen lässt sich die Behandlung nicht mehr — ablehnen schon. Sie können den Fehler weiterhin ignorieren, aber Sie müssen es hinschreiben. Und was hingeschrieben steht, kommt ins Review.
18:17 Mehr kann ein Typsystem nicht leisten, und weniger sollte es nicht. Diese Tabelle ist die Antwort auf die Grundsatzdebatte, und sie ist erfreulich unideologisch. Ein fachlich erwartbarer Fall — „Auftrag nicht gefunden", „Betrag zu hoch" — gehört als Ergebniswert modelliert; das ist kein Ausnahme-, sondern ein Normalfall.
18:36 Ein Programmierfehler oder ein gebrochener Zustand gehört dagegen zur Ausnahme; dort will man ja gerade nicht, dass jeder Aufrufer ihn behandelt. Wenn ein Fehler durch viele Ebenen durchgereicht werden soll, ist die Ausnahme bequemer. Und die letzte Zeile ist die entscheidende: Reagieren muss der Aufrufer bei der Ausnahme freiwillig, beim Ergebniswert zwangsläufig.
18:58 Der erste Punkt ist die typische Übertreibung nach der Begeisterung: Ergebnistypen für alles einsetzen und damit jede Aufrufkette aufblähen. Dann prüft man auf zwölf Ebenen etwas ab, das man nur ganz oben behandeln wollte. Der zweite: den Fehlerfall als bloße Zeichenkette modellieren, wo eine Union gebraucht wird — dann steht die Fehlerbehandlung wieder auf Textvergleichen.
19:18 Und der dritte ist der schlimmste, weil er beides entwertet: einen Ergebniswert zurückgeben und im Rumpf trotzdem werfen. Dann gilt keines von beidem, und der Aufrufer weiß gar nicht mehr, worauf er sich einstellen soll.
Übung — der Auftrag als Zustandsmaschine
19:31 Jetzt bauen Sie das alles zusammen — den ganzen Reparaturauftrag als Zustandsmaschine. Und achten Sie auf das Erfolgskriterium: Der Beweis ist ein Übersetzungsfehler, kein Testlauf. Sie sollen am Ende nicht behaupten, dass es funktioniert. Sie sollen es dem Compiler zeigen lassen. Das Lernziel: einen mehrstufigen Geschäftsprozess so in Typen fassen, dass ungültige Zustände und ungültige Übergänge gar nicht darstellbar sind.
19:58 Erfolgreich sind Sie, wenn ein neu hinzugefügter Zustand den Übersetzungslauf an jeder unbehandelten Stelle scheitern lässt — nachgewiesen, nicht behauptet. Das ist eine harte, aber sehr klare Messlatte. Wer früh fertig ist, geht einen Schritt weiter und modelliert auch die erlaubten Übergänge als eigenen Typ, nicht nur die Zustände.
20:17 Denn ein gültiger Zustand am falschen Punkt im Ablauf ist immer noch ein Fehler. Fünf Schritte, und Schritt vier ist der eigentliche Test — dort kommt die Pointe. Zuerst sammeln Sie die Zustände und notieren je Zustand die gültigen Felder. Dann schreiben Sie das als unterscheidbare Union, und zwar ohne ein einziges optionales Feld; diese Regel ist streng gemeint.
20:38 Anschließend stellen Sie die Auswertungen auf Fallunterscheidungen um und ergänzen die Vollständigkeitsprüfung. Und dann fügen Sie einen neuen Zustand hinzu und sehen sich die Fehlerliste an. Wer an dieser Stelle keine Fehler bekommt, hat das Unterscheidungsfeld zu weit typisiert — dann noch einmal zurück zu Kapitel 4. Vier Sätze zum Mitnehmen. Die Union ist das Arbeitspferd der Modellierung, die Intersection die Ausnahme.
21:03 Ein Unterscheidungsfeld macht aus einer Union ein prüfbares Zustandsmodell — das ist der wirksamste Handgriff des ganzen Tages. Der leere Typ verwandelt jeden neuen Fall in einen Übersetzungsfehler statt in einen stillen Ausfall. Und ein praktischer Hinweis für die Migration: Die Reihenfolge der Union-Glieder war nie zugesichert, TypeScript 7 ordnet sie anders.
21:23 Im nächsten Modul verlassen wir für einen Moment das Typsystem und schauen, wie sich diese Modelle mit einem Coding Agent erarbeiten lassen — und wo der zuverlässig danebenliegt.
Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →