Record
Manche Daten bilden eine Tabelle: ein Wert für jedes Glied einer Literal-Union. Wenn ein Held ein Monster besiegt, bekommt er Erfahrungspunkte (EP), und wie viele es sind, hängt von der Art des Monsters ab:
type MonsterArt = "wolf" | "troll" | "drache";
const erfahrungFuer = {
wolf: 15,
troll: 40,
};Jemand hat den Drachen vergessen. TypeScript kann nicht wissen, dass dieses Objekt für jede MonsterArt einen Schlüssel haben soll, solange du es ihm nicht sagst. Dafür hat es einen fertigen Typ, Record:
type MonsterArt = "wolf" | "troll" | "drache";
const erfahrungFuer: Record<MonsterArt, number> = {
wolf: 15,
troll: 40,
};main.ts(3,7): error TS2741: Property 'drache' is missing in type '{ wolf: number; troll: number; }' but required in type 'Record<MonsterArt, number>'.Record<MonsterArt, number> bedeutet „ein Objekt mit genau den Schlüsseln aus MonsterArt und einer Zahl für jeden von ihnen“. Du gibst Record zwei Typen in spitzen Klammern: zuerst den Typ der Schlüssel, dann den Typ der Werte. (Wie Typen mit spitzen Klammern funktionieren und wie du eigene schreibst, lernst du in der Lektion über Generics.) TypeScript prüft dann die Tabelle. Ein fehlender Schlüssel ergibt TS2741, wie oben. Ein falsch geschriebener Schlüssel, etwa drach: 100, ergibt:
main.ts(6,5): error TS2561: Object literal may only specify known properties, but 'drach' does not exist in type 'Record<MonsterArt, number>'. Did you mean to write 'drache'?Und ein Wert vom falschen Typ, etwa wolf: "15", ergibt TS2322.
Du liest die Tabelle mit eckigen Klammern, wie du es mit vorrat[frucht] im JavaScript-Kurs getan hast:
type MonsterArt = "wolf" | "troll" | "drache";
type Monster = { name: string; art: MonsterArt };
const erfahrungFuer: Record<MonsterArt, number> = {
wolf: 15,
troll: 40,
drache: 100,
};
const grak: Monster = { name: "Grak", art: "troll" };
console.log(`${grak.name} gibt ${erfahrungFuer[grak.art]} EP`);Das gibt aus:
Grak gibt 40 EPDer Typ von grak.art ist MonsterArt, TypeScript weiß also, dass der Schlüssel existiert, und das Ergebnis ist eine number. Mit einem Schlüssel, der irgendein Text ist, ist das Lesen ein Fehler, weil der Text gar kein Schlüssel sein könnte. Setze diese zwei Zeilen direkt unter das }; der Tabelle, in die Zeilen 9 und 10:
const schluessel: string = "troll";
console.log(erfahrungFuer[schluessel]);main.ts(10,13): error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Record<MonsterArt, number>'.
No index signature with a parameter of type 'string' was found on type 'Record<MonsterArt, number>'.Die Meldung sagt, dass TypeScript einen string nicht verwenden kann, um aus einem Record<MonsterArt, number> zu lesen, das Ergebnis hätte also den Typ any. Die Lösung ist, dem Schlüssel den richtigen Typ zu geben, MonsterArt.
Auch zum Zählen ist ein Record praktisch. Beginne jeden Schlüssel bei 0 und addiere in einer Schleife eins:
type MonsterArt = "wolf" | "troll" | "drache";
type Monster = { name: string; art: MonsterArt };
const besiegt: Monster[] = [
{ name: "Grak", art: "troll" },
{ name: "Fang", art: "wolf" },
{ name: "Schatten", art: "wolf" },
];
const zaehler: Record<MonsterArt, number> = { wolf: 0, troll: 0, drache: 0 };
for (const monster of besiegt) {
zaehler[monster.art]++;
}
console.log(zaehler);Das gibt aus:
{ wolf: 2, troll: 1, drache: 0 }So schreibst du es:
Anweisungen
- 1
Gib
preiseden TypRecord<Seltenheit, number>. TypeScript meldet dann den fehlenden Preis: Füge ihn hinzu. Ein legendärer Gegenstand kostet200Gold. - 2
Gib den Preis jedes Gegenstands im Inventar aus, mit
preiseund der Seltenheit des Gegenstands. Das Programm gibt dann aus:Seil: 10 Gold Silberschwert: 50 Gold Drachenei: 200 Gold Fackel: 10 Gold - 3
Zähle die Gegenstände jeder Seltenheit in
const anzahlen: Record<Seltenheit, number>und gib die Anzahlen am Ende aus:Seil: 10 Gold Silberschwert: 50 Gold Drachenei: 200 Gold Fackel: 10 Gold Gewöhnlich: 2, selten: 1, legendär: 1