🧩Das Typsystem
Ein Typ ist eine Menge möglicher Werte. string umfasst alle Texte, "hallo" genau einen, never keinen. Mit diesem Bild lassen sich fast alle Regeln des Typsystems erklären.
🧱Grundtypen
| Typ | Beispiel | Werte | Hinweis |
|---|---|---|---|
| string | let name: string = "Ada"; | alle Texte | Klein geschrieben! String (groß) ist der Wrapper-Objekttyp. |
| number | let preis: number = 9.99; | Gleitkommazahlen (IEEE 754) inkl. NaN, Infinity | Es gibt kein separates int. |
| bigint | let gross: bigint = 2n ** 64n; | beliebig große Ganzzahlen | Nicht mit number mischbar. |
| boolean | let aktiv: boolean = true; | true, false | Intern die Union true | false. |
| null / undefined | let leer: null = null; | je genau ein Wert | Mit strictNullChecks eigene Typen, sonst in jedem Typ enthalten. |
| symbol | let id: symbol = Symbol("id"); | eindeutige Schlüssel | unique symbol für Konstanten. |
| T[] / Array<T> | let zahlen: number[] = [1, 2, 3]; | Listen beliebiger Länge | Beide Schreibweisen sind gleichwertig. |
| [A, B] | let paar: [string, number] = ["x", 1]; | Tupel: feste Länge, Typ pro Position | Mit Namen: [name: string, alter: number]. |
| object / { … } | let p: { x: number; y: number } = { x: 1, y: 2 }; | Objekte mit dieser Struktur | object = alles Nicht-Primitive. |
| (a: A) => R | let f: (n: number) => string = String; | Funktionen | Parameternamen sind nur Dokumentation. |
| void | function log(): void {} | „kein sinnvoller Rückgabewert“ | Nur als Rückgabetyp üblich. |
🎭any, unknown und never
Drei Sonderfälle: unknown ist die Menge aller Werte (oben), never die leere Menge (unten). any steht außerhalb – es ist in beide Richtungen zuweisbar und schaltet die Prüfung ab.
unknown ← alle Werte ("top type")
┌───────────┼─────────────┬──────────┐
object string number null undefined …
│ │ │
{ x: 1 } … "hallo" … 42 … ← Literal-Typen
└───────────┼─────────────┘
never ← kein Wert ("bottom type")
any = „Typprüfung aus“: passt überall hin und nimmt alles anTypeScript · bearbeitbar, Maus über Namen zeigt Typen
Zuweisbarkeit – berechnet vom Compiler
| Wert vom Typ … ↓ · … zuweisbar an → | any | unknown | never | string | "hallo" | number | null | undefined | object | {} |
|---|---|---|---|---|---|---|---|---|---|---|
| any | · | · | · | · | · | · | · | · | · | · |
| unknown | · | · | · | · | · | · | · | · | · | · |
| never | · | · | · | · | · | · | · | · | · | · |
| string | · | · | · | · | · | · | · | · | · | · |
| "hallo" | · | · | · | · | · | · | · | · | · | · |
| number | · | · | · | · | · | · | · | · | · | · |
| null | · | · | · | · | · | · | · | · | · | · |
| undefined | · | · | · | · | · | · | · | · | · | · |
| object | · | · | · | · | · | · | · | · | · | · |
| {} | · | · | · | · | · | · | · | · | · | · |
Fahren Sie über eine Zelle.
- Spalte
unknown: alles grün – jeder Wert passt hinein. - Zeile
never: alles grün – die leere Menge ist Teilmenge von allem. {}heißt „alles außernull/undefined“ – nicht „leeres Objekt“.
🔤Literal-Typen & Widening
Ein Literal-Typ enthält genau einen Wert. Ob TypeScript den genauen oder einen „verbreiterten“ Typ ableitet, hängt davon ab, ob sich der Wert später ändern kann.
| Code | Typ laut Compiler | Warum? |
|---|---|---|
| let a = "hallo"; | … | let kann sich ändern → der Literal-Typ wird zu string verbreitert (Widening). |
| const b = "hallo"; | … | const ändert sich nie → der Typ bleibt das Literal "hallo". |
| const c = 42; | … | Auch Zahlen können Literal-Typen sein. |
| const d = { modus: "hell" }; | … | Eigenschaften sind veränderbar → modus wird string. |
| const e = { modus: "hell" } as const; | … | as const friert alles ein: readonly und Literal-Typen. |
| const f = [1, 2, 3]; | … | Array-Literal → number[]. |
| const g = [1, 2, 3] as const; | … | Mit as const ein schreibgeschütztes Tupel. |
| let h: "hell" | "dunkel" = "hell"; | … | Eine Union von Literalen als erlaubte Werteliste. |
⭕Union & Intersection als Mengen
A | B vereinigt die Wertemengen, A & B schneidet sie. Wählen Sie zwei Typen – Ergebnis und Diagramm kommen vom Compiler.
Compiler rechnet …
Vereinigung · A | B · „das eine oder das andere“
…Alle Werte, die zu A oder B passen. Man darf nur verwenden, was alle Mitglieder gemeinsam haben – bis man eingrenzt (Narrowing).
Schnitt · A & B · „beides zugleich“
…Nur Werte, die zu A und B passen. Bei primitiven Typen bleibt oft wenig übrig (oder never).
Berechnet vom Compiler aus:
type Vereinigung = string | number | number | boolean; type Schnitt = (string | number) & (number | boolean);💡 Paradox bei Objekten?
MitName & MitAlter hat mehr Eigenschaften als jeder Teil – beschreibt aber weniger Werte (nur Objekte mit beiden Eigenschaften). Bei der Union ist es umgekehrt: mehr Werte, aber sicher nutzbar sind nur gemeinsame Eigenschaften, bis man mitin eingrenzt.TypeScript · bearbeitbar, Maus über Namen zeigt Typen
🦆Strukturelle Typisierung
TypeScript vergleicht Typen nach ihrer Form, nicht nach ihrem Namen („Duck Typing“): Wer mindestens die geforderten Eigenschaften hat, passt – egal wie sein Typ heißt.
TypeScript · bearbeitbar, Maus über Namen zeigt Typen
⚠️ Ausnahme: frische Objektliterale
Direkt geschriebene Objektliterale mit zusätzlichen Eigenschaften lehnt der Compiler ab (Excess Property Check, TS2353) – obwohl sie strukturell passen würden. Das fängt Tippfehler ab.
| Wert vom Typ … ↓ · … zuweisbar an → | Punkt2D | Punkt3D | Benannt | BenannterPunkt | OptionalZ | Leer |
|---|---|---|---|---|---|---|
| Punkt2D | · | · | · | · | · | · |
| Punkt3D | · | · | · | · | · | · |
| Benannt | · | · | · | · | · | · |
| BenannterPunkt | · | · | · | · | · | · |
| OptionalZ | · | · | · | · | · | · |
| Leer | · | · | · | · | · | · |
Fahren Sie über eine Zelle.
Punkt3D passt an Punkt2D (hat x und y – und mehr), umgekehrt nicht. An Leer passt alles, weil nichts verlangt wird.
⚖️interface oder type?
Für Objektformen sind beide fast austauschbar. Die Unterschiede:
| Merkmal | interface | type |
|---|---|---|
| Objektform beschreiben | ✅ interface P { x: number } | ✅ type P = { x: number } |
| Erweitern | ✅ interface B extends A { … } | ✅ type B = A & { … } |
| Unions, Tupel, Primitive | ❌ | ✅ type Id = string | number |
| Mapped/Conditional Types | ❌ | ✅ |
| Declaration Merging (zweimal deklarieren = zusammenführen) | ✅ z. B. um globale Typen zu ergänzen | ❌ Fehler: Doppelter Bezeichner |
| Von Klassen implementierbar | ✅ | ✅ (wenn Objekttyp) |
Declaration Merging · bearbeitbar, Maus über Namen zeigt Typen
🔒Optionale und readonly-Eigenschaften
? erlaubt, dass eine Eigenschaft fehlt (ihr Typ enthält dann undefined). readonly verbietet Zuweisungen nach dem Erzeugen – nur zur Compile-Zeit.TypeScript · bearbeitbar, Maus über Namen zeigt Typen
JavaScript (erzeugt von tsc) · …nur lesen