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 }

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ých

Spočí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í: 1

Začněte programovat zdarma

Registrací souhlasíte s provozními podmínkami a zásadami ochrany osobních údajů.

Nebo se registrujte pomocí:

4/8