Kodokon kodokon.com

Generics: einfache generische Funktionen und Typen

Schreibe wiederverwendbare Funktionen und Typen, die bei jedem Aufruf die volle Typgenauigkeit behalten.

9 Min. · 3 Fragen

Diese Lektion in Kodokon öffnen

Du verwendest Generics längst, ohne es zu merken: string[], Promise<number>... Zeit, eigene zu schreiben. Ein Generic führt einen Typparameter ein, also eine Variable, die bei jeder Verwendung durch einen konkreten Typ ersetzt wird. Das Ziel: die Logik einmal schreiben, ohne auf Typgenauigkeit zu verzichten.

TYPESCRIPT
function first<T>(items: T[]): T | undefined {
  return items[0];
}

const n = first([10, 20, 30]);
const s = first(["a", "b"]);
T wird abgeleitet: n ist number | undefined, s ist string | undefined

Beachte, dass du an der Aufrufstelle nichts angegeben hast: TypeScript leitet T aus dem Argument ab. Ein Generic ohne Einschränkung akzeptiert alles; oft braucht eine Funktion aber ein Minimum an Garantien über ihre Daten. Das Schlüsselwort extends erzwingt eine minimale Form für T.

TYPESCRIPT
interface HasId {
  id: number;
}

function findById<T extends HasId>(
  items: T[],
  id: number
): T | undefined {
  return items.find((item) => item.id === id);
}
Constraint: T muss mindestens eine numerische id haben

Typen selbst können generisch sein. Das ist Alltag im Netzwerkcode: Die Struktur der Antwort ist stabil, nur der Inhalt von data variiert. Ein einziger Typ beschreibt dann alle deine API-Antworten.

TYPESCRIPT
interface ApiResponse<T> {
  ok: boolean;
  data: T;
}

type UserResponse = ApiResponse<{ name: string }>;

const res: UserResponse = {
  ok: true,
  data: { name: "Ada" },
};
Ein generischer Typ parametrisiert den Inhalt von data

Wissenscheck

Stelle sicher, dass du die wichtigsten Punkte dieser Lektion behalten hast.

  1. Wofür steht T in function first<T>(items: T[]): T | undefined?
    • Für einen konkreten Typ, der ein für alle Mal festgelegt ist
    • Für einen Typparameter, der bei jedem Aufruf ersetzt wird
    • Für den Typ unknown
    • Für eine Kurzform von any
  2. Was garantiert der Constraint <T extends HasId>?
    • T ist genau der Typ HasId
    • T hat mindestens die Eigenschaften von HasId
    • T erbt von der Klasse HasId
  3. Du rufst first([10, 20, 30]) auf, ohne einen Typ anzugeben. Was ist T?
    • any
    • unknown
    • number
    • 10 | 20 | 30