Generische Typen
Du kannst auch eigene generische Typen deklarieren. Ein Laden verkauft Kisten. Jede Kiste hat ein Etikett, aber der Inhalt ist verschieden: Münzen, Pfeile, ein Schwert. Statt eines Typs für jede Art Kiste deklarierst du einen Typ mit einem Typparameter:
type Kiste<T> = { etikett: string; inhalt: T };Der Typparameter steht in spitzen Klammern hinter dem Namen des Typs, und im Typ wird T wie jeder andere Typ verwendet. Kiste<number> ist dann { etikett: string; inhalt: number }, und Kiste<string[]> ist eine Kiste mit einem Array von Texten. TypeScript prüft den Inhalt gegen das Typargument:
type Kiste<T> = { etikett: string; inhalt: T };
const muenzen: Kiste<number> = { etikett: "Münzen", inhalt: 50 };
const pfeile: Kiste<string[]> = { etikett: "Pfeile", inhalt: ["Feuerpfeil", "Eispfeil"] };
const schwert: Kiste<number> = { etikett: "Schwert", inhalt: "Silberschwert" };TypeScript meldet:
main.ts(5,54): error TS2322: Type 'string' is not assignable to type 'number'.Die Kiste schwert sagt, dass sie eine Zahl enthält. Bei einer Variablen schreibst du das Typargument immer; ohne es ergibt const schwert: Kiste = … die Meldung Generic type 'Kiste' requires 1 type argument(s). (TS2314), wie bei Array.
Auch Interfaces können Typparameter haben, und ein Typ kann mehrere haben:
interface Regal<T> {
name: string;
gegenstaende: T[];
}
type Paar<A, B> = [A, B];
const trankRegal: Regal<string> = { name: "Tränke", gegenstaende: ["Heiltrank", "Elixier"] };
const preisschild: Paar<string, number> = ["Silberschwert", 120];Generische Typen in generischen Funktionen. Eine Funktion, die jede Kiste akzeptiert, ist ebenfalls generisch:
type Kiste<T> = { etikett: string; inhalt: T };
function auspacken<T>(kiste: Kiste<T>): T {
console.log(`Auspacken: ${kiste.etikett}`);
return kiste.inhalt;
}
const muenzen: Kiste<number> = { etikett: "Münzen", inhalt: 50 };
const gold = auspacken(muenzen) + 20;
console.log(gold);Das gibt aus:
Auspacken: Münzen
70In auspacken(muenzen) sieht TypeScript, dass muenzen eine Kiste<number> ist, also ist T gleich number und auspacken gibt eine Zahl zurück: 20 dazuzuzählen ist in Ordnung. Bei einer Kiste<string[]> würde es ein string[] zurückgeben.
So schreibst du es:
Anweisungen
- 1
Deklariere einen generischen Typ
Truhe<T>für eine Truhe mit einemort(ein Text) und einerbeutevom TypT. Erstelle dann zwei Truhen:goldTruhevom TypTruhe<number>in der"Goblinhöhle"mit der Beute120undtrankTruhevom TypTruhe<string[]>im"Magierturm"mit der Beute["Heiltrank", "Elixier"]. - 2
Schreibe eine generische Funktion
oeffneTruhe<T>(truhe: Truhe<T>): T. Sie gibtÖffne die Truhe ingefolgt vom Ort der Truhe aus, zum BeispielÖffne die Truhe in Goblinhöhle, und gibt die Beute der Truhe zurück. - 3
Kira öffnet beide Truhen. Füge diese Zeilen am Ende des Programms hinzu:
gold = gold + oeffneTruhe(goldTruhe); for (const trank of oeffneTruhe(trankTruhe)) { inventar.push(trank); } console.log(`Gold: ${gold}`); console.log(inventar);Das Programm gibt aus:
Öffne die Truhe in Goblinhöhle Öffne die Truhe in Magierturm Gold: 170 ["Bogen", "Heiltrank", "Elixier"]TypeScript weiß, dass der erste Aufruf eine Zahl zurückgibt, die zu
goldaddiert werden kann, und der zweite einstring[], dessen Elemente ininventarpassen.