1.5 TypeScript: Typen als Werkzeug
Nach dieser Einheit kannst du:
- erklären, welche Fehlerklasse TypeScript vor dem Programmlauf abfängt und warum zur Laufzeit trotzdem gewöhnliches JavaScript läuft.
- Daten mit Annotationen,
interfaceund Union Types beschreiben. - TypeScript mit
tscundtsxausführen und begründen, warum erstnpm run typecheckdie Typen beweist.
Erinnere dich an den Paketdienst aus Einheit 1.1: Er prüft jedes Etikett am Förderband, bevor der Lkw losfährt, oder er stellt einfach zu und hofft, dass sich die Empfängerin schon meldet, wenn etwas nicht stimmt. Bisher hast du mit JavaScript nach der zweiten Methode gearbeitet. Ab dieser Einheit kommt die Kontrolle am Förderband dazu.
Diese Einheit zeigt, welche Fehler die Kontrolle findet, wie du Daten so beschreibst, dass sie prüfbar werden, und mit welchen Werkzeugen TypeScript-Code geprüft und gestartet wird. Am Ende setzt ein vollständiges Beispiel die Bausteine zusammen.
Begriffe vorab
Abschnitt betitelt „Begriffe vorab“- Compiler (
tsc): übersetzt TypeScript in JavaScript und meldet dabei Typfehler. - Typannotation: eine Typangabe im Code, etwa
: numberhinter einem Parameter. - Typinferenz: TypeScript erschließt einen Typ selbst, wo er aus dem Code ersichtlich ist.
- Interface: beschreibt die Form eines Objekts, also Felder und ihre Typen.
- Union Type: ein Typ, der eine von mehreren aufgezählten Möglichkeiten erlaubt.
- Generic: ein Typ mit Platzhalter, der beim Verwenden durch einen echten Typ ersetzt wird.
TypeScript: Typen als Werkzeug
Abschnitt betitelt „TypeScript: Typen als Werkzeug“JavaScript prüft Typen erst zur Laufzeit, und ist dann (sehr, sehr) tolerant:
function totalDuration(clips) { return clips.reduce((sum, clip) => sum + clip.durationSeconds, 0);}
totalDuration([{ filename: "intro.mp4", durationSecond: 90 }]); // NaNBeispielprojekt: 01_typescript_examples/ex15_js_without_types
Der Tippfehler durationSecond (ohne s) fällt nicht auf: Der Zugriff liefert undefined, die Addition NaN, und das Programm läuft mit diesem Unsinn weiter. Solche Fehler kosten in wachsenden Projekten die meiste Debugging-Zeit.
Genau gegen sie ist TypeScript gebaut: JavaScript plus Typangaben, geprüft vor dem Programmlauf vom Compiler tsc. TypeScript wird zu gewöhnlichem JavaScript übersetzt; im Browser und in Node läuft am Ende immer JavaScript.
Zurück zum Paketdienst vom Anfang dieser Einheit: tsc ist die Kontrolle am Förderband. Sie findet das falsch beschriftete Paket, solange es noch in der Halle steht - nicht erst, wenn die Kundin (oder der Benutzer deiner Anwendung) es auspackt. Die Grenze des Bildes: Die Kontrolle liest nur Etiketten, die im eigenen Lager geklebt wurden. Was von außen kommt, etwa die Antwort eines Servers, hat für tsc kein Etikett; wie man damit umgeht, zeigt Einheit 1.6.
Typannotationen und Inferenz
Abschnitt betitelt „Typannotationen und Inferenz“function totalDuration(clips: Clip[]): number { return clips.reduce((sum, clip) => sum + clip.durationSeconds, 0);}
let attempts: number = 0; // explicitlet name = "Ada"; // inferred as string; annotation unnecessaryDie Syntax folgt dem Muster wert: Typ, der Rückgabetyp steht nach der Parameterliste. TypeScript inferiert Typen, wo es sie sehen kann; annotiert werden vor allem Funktionsparameter und Datenstrukturen, nicht jede lokale Variable.
Interfaces: die Form der Daten
Abschnitt betitelt „Interfaces: die Form der Daten“interface Clip { filename: string; durationSeconds: number; tags: string[]; fps?: number; // optional property}
const intro: Clip = { filename: "intro.mp4", durationSeconds: 90, tags: ["opener"],};Beispielprojekt: 01_typescript_examples/ex16_annotations_interfaces
Ein interface beschreibt die Form eines Objekts: welche Felder, welche Typen, was optional ist (?). Der Tippfehler von oben ist damit ein Compile-Fehler mit präziser Meldung, noch bevor das Programm startet: 'durationSecond' does not exist in type 'Clip'. Did you mean to write 'durationSeconds'? Interfaces sind zugleich Dokumentation: Wer Clip liest, kennt den Datenvertrag, ohne Code zu lesen. Genau in dieser Rolle begleiten sie das ganze Jahr, als Verträge für API-Daten.
Union Types und Literale
Abschnitt betitelt „Union Types und Literale“type RenderState = "queued" | "running" | "done" | "failed";
function label(state: RenderState): string { if (state === "done") return "finished"; return state;}
label("dne"); // compile error: not assignable to RenderStateBeispielprojekt: 01_typescript_examples/ex17_union_types
Ein Union Type zählt die erlaubten Möglichkeiten auf. Der Klassiker sind Zustands- und Statusfelder: Statt beliebiger Strings gibt es vier gültige Werte, und jeder Tippfehler fliegt beim Kompilieren auf. Auch Kombinationen wie string | null (“String oder bewusst leer”) sind Union Types; TypeScript zwingt dann an jeder Verwendungsstelle zur Behandlung des null-Falls.
TypeScript ausführen
Abschnitt betitelt „TypeScript ausführen“npm install --save-dev typescript tsxnpx tsc --init # creates tsconfig.jsonnpx tsc # type-check and compile to JavaScriptnpx tsx timecode.ts # run directly during development (tsx package)Im Alltag dieses Jahres übernimmt Next.js die komplette TypeScript-Werkzeugkette unsichtbar; tsc von Hand zu bedienen gehört trotzdem einmal erlebt, damit klar ist, was das Framework automatisiert. In der tsconfig.json bleibt die Voreinstellung "strict": true unangetastet: Der strenge Modus findet die meisten Fehler, und sich später an Strenge zu gewöhnen ist erfahrungsgemäß viel schwerer. npx tsc --init (TypeScript 7) schaltet außerdem noUncheckedIndexedAccess ein: Ein Array-Zugriff wie items[0] hat dann den Typ T | undefined, weil das Array leer sein könnte. Dazu kommt exactOptionalPropertyTypes, das bei einem optionalen Feld wie fps?: number ein ausdrücklich zugewiesenes undefined verbietet; der Kurs behält beide Einstellungen bei.
Wo begegnet dir das? Schon in deinem Editor: VS Code ist selbst in TypeScript geschrieben, und die roten Unterstreichungen in .ts-Dateien kommen von demselben Compiler, den du mit tsc startest. Auch create-next-app aus Kapitel 8 schlägt TypeScript als Voreinstellung vor.
Auflösung
Auch hier meldet tsc einen Fehler: Argument of type 'string' is not assignable to parameter of type 'RenderState'. Der Compiler kennt nur den Typ string der Variablen, nicht ihren Wert, und nicht jeder String ist ein gültiger Zustand. Erst eine Prüfung (etwa if (input === "done" || input === "queued" ...)) grenzt den Typ ein. Genau dieses Prüfen statt Behaupten ist das Thema von Einheit 1.6.
Ein vollständiges Beispiel
Abschnitt betitelt „Ein vollständiges Beispiel“Ein kleines typisiertes Werkzeug, das die Bausteine kombiniert: Aus einer Liste von Videoclips soll die Gesamtdauer je Tag berechnet werden.
interface Clip { filename: string; durationSeconds: number; tags: string[];}
function durationByTag(clips: Clip[]): Map<string, number> { const totals = new Map<string, number>(); for (const clip of clips) { for (const tag of clip.tags) { totals.set(tag, (totals.get(tag) ?? 0) + clip.durationSeconds); } } return totals;}
const clips: Clip[] = [ { filename: "intro.mp4", durationSeconds: 90, tags: ["opener"] }, { filename: "interview.mp4", durationSeconds: 845, tags: ["main", "voice"] }, { filename: "outro.mp4", durationSeconds: 45, tags: ["opener"] },];
for (const [tag, seconds] of durationByTag(clips)) { console.log(`${tag}: ${seconds} s`);}Beispielprojekt: 01_typescript_examples/ex19_duration_by_tag
Beachtenswert: das Interface als Datenvertrag, Map<string, number> als Generic in Verwendung, ?? 0 für den ersten Treffer eines Tags und Destructuring in der Ausgabeschleife. Jeder Tippfehler in einem Feldnamen wäre ein Compile-Fehler.
Wo begegnet dir das? Summieren nach einem Merkmal ist eine der häufigsten Auswertungen überhaupt: Ausgaben je Kategorie in einer Banking-App, Bildschirmzeit je App in den Handy-Einstellungen, Spielzeit je Spiel auf einer Gaming-Plattform. Das Prinzip ist jedes Mal dasselbe wie in durationByTag: eine Schleife über die Einträge und eine Map vom Merkmal auf die laufende Summe.
Stolperfallen
Abschnitt betitelt „Stolperfallen“undefinedstatt Fehler: In JavaScript liefert der Zugriff auf ein nicht existierendes Feldundefinedund knallt erst später. In TypeScript wird daraus ein Compile-Fehler; einer der Hauptgründe für die Sprache.- Programm läuft, also stimmen die Typen:
tsxstartet auch Dateien mit Typfehlern. Erstnpm run typecheck(tsc --noEmit) beweist, dass der Compiler zufrieden ist. - Wert und Typ verwechselt: Bei
const input: string = "done";kennt der Compiler nur den Typstring, nicht den Wert. Ein Union Type wieRenderStatenimmt die Variable deshalb erst nach einer Prüfung an. strictabgeschaltet: Wer Fehlermeldungen loswerden will, indem er in dertsconfig.jsonden strengen Modus abdreht, verliert genau die Prüfungen, für die TypeScript da ist. Die Voreinstellung bleibt.
Zusatzmaterialien
Abschnitt betitelt „Zusatzmaterialien“- TypeScript-Handbuch - die offizielle, gut lesbare Referenz; das Kapitel Everyday Types deckt diese Einheit fast vollständig ab.
- TypeScript-Handbuch: Everyday Types - Annotationen, Inferenz, Interfaces, Union Types und Literal-Typen an einem Stück.
- TypeScript Playground - TypeScript im Browser ausprobieren, ohne Installation; rechts siehst du sofort das erzeugte JavaScript und alle Compiler-Meldungen.
Zum Anhören
Abschnitt betitelt „Zum Anhören“Du kannst dir diese Einheit kostenlos mit der Vorlesefunktion deines Browsers oder Betriebssystems vorlesen lassen (etwa „Laut vorlesen” in Edge), ohne Konto und ohne Upload; die Codebeispiele liest du dabei am Bildschirm mit. Freiwillig kannst du mit Google NotebookLM (Google-Konto nötig) aus diesem öffentlichen Text eine gesprochene Zusammenfassung erzeugen, auch auf Deutsch.
Lernergebnisse
Abschnitt betitelt „Lernergebnisse“Du kannst jetzt:
- erklären, welche Fehlerklasse TypeScript vor dem Programmlauf abfängt und warum zur Laufzeit trotzdem gewöhnliches JavaScript läuft.
- Daten mit Annotationen,
interfaceund Union Types beschreiben. - TypeScript mit
tscundtsxausführen und begründen, warum erstnpm run typecheckdie Typen beweist.
Passende Übungen
Abschnitt betitelt „Passende Übungen“- Aufgabe 02 - Typen retten den Tag, Stufen Wesentlich_überwiegend und Wesentlich_vollständig
- Aufgabe 03 - TypeScript-Katas, Stufen Wesentlich_überwiegend und Wesentlich_vollständig
Quellen
Abschnitt betitelt „Quellen“- VS Code ist in TypeScript geschrieben → microsoft/vscode auf GitHub
create-next-applegt standardmäßig ein TypeScript-Projekt an → Next.js-Dokumentation: create-next-app- Typannotationen, Inferenz, Interfaces, Union Types → TypeScript-Handbuch: Everyday Types
- TypeScript 7: Voreinstellungen von
tsc --init(noUncheckedIndexedAccess,exactOptionalPropertyTypes), Meldung TS2561 → eigener Test mit TypeScript 7.0.2 (Oktober 2026); TSConfig-Referenz: noUncheckedIndexedAccess - TypeScript allgemein,
tscundtsconfig.json→ TypeScript-Handbuch, TypeScript Playground - Abb. 1.1 (Paketdienst), Abb. 1.13 (Kontrolle am Förderband:
tscvor dem Programmlauf), Abb. 1.14 (Interface als Vertrag), Abb. 1.15 (Mapje Tag) → eigene Darstellung
Autoren
Abschnitt betitelt „Autoren“- Oliver Maurhart (MAO)
- Michael Gabriel (GAM)
CC-BY-SA