Record
Některá data jsou tabulka: jedna hodnota pro každý člen sjednocení literálů. Když hrdina porazí příšeru, dostane zkušenosti, a kolik jich dostane, záleží na typu příšery:
type TypPrisery = "vlk" | "troll" | "drak";
const zkusenostiZa = {
vlk: 15,
troll: 40,
};Někdo zapomněl na draka. TypeScript nemůže vědět, že by tenhle objekt měl mít klíč pro každý TypPrisery, pokud mu to neřeknete. K tomu má připravený typ Record (anglicky „záznam“):
type TypPrisery = "vlk" | "troll" | "drak";
const zkusenostiZa: Record<TypPrisery, number> = {
vlk: 15,
troll: 40,
};main.ts(3,7): error TS2741: Property 'drak' is missing in type '{ vlk: number; troll: number; }' but required in type 'Record<TypPrisery, number>'.Record<TypPrisery, number> znamená „objekt, který má přesně klíče z typu TypPrisery a u každého z nich číslo“. Typu Record dáte do špičatých závorek dva typy: nejdřív typ klíčů, pak typ hodnot. (Jak typy se špičatými závorkami fungují a jak napsat vlastní, se naučíte v lekci Generika.) TypeScript pak tabulku zkontroluje. Chybějící klíč skončí chybou TS2741 jako výše. Klíč s překlepem, třeba drk: 100, skončí touhle chybou:
main.ts(6,5): error TS2561: Object literal may only specify known properties, but 'drk' does not exist in type 'Record<TypPrisery, number>'. Did you mean to write 'drak'?A hodnota špatného typu, třeba vlk: "15", chybou TS2322.
Z tabulky čtete pomocí hranatých závorek, stejně jako sklad[ovoce] v kurzu JavaScriptu:
type TypPrisery = "vlk" | "troll" | "drak";
type Prisera = { jmeno: string; typ: TypPrisery };
const zkusenostiZa: Record<TypPrisery, number> = {
vlk: 15,
troll: 40,
drak: 100,
};
const grak: Prisera = { jmeno: "Grak", typ: "troll" };
console.log(`${grak.jmeno}: ${zkusenostiZa[grak.typ]} zkušeností`);Vypíše:
Grak: 40 zkušenostígrak.typ je typu TypPrisery, takže TypeScript ví, že klíč existuje, a výsledek je number. S klíčem, který je jen nějaký text, je čtení chyba, protože ten text vůbec nemusí být klíčem. Když hned pod tabulku, na řádky 9 a 10, napíšete:
const text: string = "troll";
console.log(zkusenostiZa[text]);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<TypPrisery, number>'.
No index signature with a parameter of type 'string' was found on type 'Record<TypPrisery, number>'.Hláška říká, že TypeScript nemůže pomocí hodnoty typu string číst z Record<TypPrisery, number>, a výsledek by tak měl typ any. Opravou je dát klíči správný typ, TypPrisery.
Record se hodí i na počítání. Každý klíč nastavte na 0 a v cyklu přičítejte jedničku:
type TypPrisery = "vlk" | "troll" | "drak";
type Prisera = { jmeno: string; typ: TypPrisery };
const porazene: Prisera[] = [
{ jmeno: "Grak", typ: "troll" },
{ jmeno: "Tesák", typ: "vlk" },
{ jmeno: "Stín", typ: "vlk" },
];
const pocty: Record<TypPrisery, number> = { vlk: 0, troll: 0, drak: 0 };
for (const prisera of porazene) {
pocty[prisera.typ]++;
}
console.log(pocty);Vypíše:
{ vlk: 2, troll: 1, drak: 0 }Jak psát:
Pokyny
Dejte konstantě ceny typ Record<Vzacnost, number>. TypeScript pak ohlásí chybějící cenu: doplňte ji. Legendární předmět stojí 200 zlatých.
Vypište cenu každého předmětu v inventáři pomocí ceny a vzácnosti předmětu. Program pak vypíše:
Lano: 10 zlatých
Stříbrný meč: 50 zlatých
Dračí vejce: 200 zlatých
Pochodeň: 10 zlatýchSpočítejte předměty každé vzácnosti v const pocty: Record<Vzacnost, number> a na konci počty vypište:
Lano: 10 zlatých
Stříbrný meč: 50 zlatých
Dračí vejce: 200 zlatých
Pochodeň: 10 zlatých
Běžné: 2, vzácné: 1, legendární: 1Začněte programovat zdarma
4/8