keyof
Někdy je klíč, který chcete přečíst, uložený v proměnné. V JavaScriptu byste napsali schopnosti[klic], s hranatými závorkami. V TypeScriptu:
type Schopnosti = { sila: number; obratnost: number; magie: number };
const kira: Schopnosti = { sila: 6, obratnost: 9, magie: 4 };
function hodnotaSchopnosti(schopnosti: Schopnosti, klic: string): number {
return schopnosti[klic];
}
console.log(hodnotaSchopnosti(kira, "obratnost"));TypeScript ohlásí:
main.ts(4,12): error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Schopnosti'.
No index signature with a parameter of type 'string' was found on type 'Schopnosti'.TypeScript odmítne, protože klic může být jakýkoli text, třeba "magi", a typ Schopnosti má jen tři klíče. Pro každý jiný klíč by schopnosti[klic] bylo undefined, a ne číslo, takže TypeScript nedokáže říct, jaký typ výsledek má („implicitly has an 'any' type“).
Typ „jeden z klíčů typu Schopnosti“ se zapíše jako keyof Schopnosti:
type Schopnosti = { sila: number; obratnost: number; magie: number };
type NazevSchopnosti = keyof Schopnosti; // "sila" | "obratnost" | "magie"keyof vezme objektový typ a vrátí sjednocení jeho klíčů jako literálových typů. Protože se počítá z typu, nemůže zastarat: když do typu Schopnosti přidáte klíč, bude ho mít i keyof Schopnosti. S klic: keyof Schopnosti je schopnosti[klic] dovolené a překlep v klíči se odhalí už tam, kde funkci voláte:
type Schopnosti = { sila: number; obratnost: number; magie: number };
const kira: Schopnosti = { sila: 6, obratnost: 9, magie: 4 };
function hodnotaSchopnosti(schopnosti: Schopnosti, klic: keyof Schopnosti): number {
return schopnosti[klic];
}
console.log(hodnotaSchopnosti(kira, "obratnost"));
console.log(hodnotaSchopnosti(kira, "magi"));TypeScript ohlásí:
main.ts(7,37): error TS2345: Argument of type '"magi"' is not assignable to parameter of type 'keyof Schopnosti'.keyof a generika. Když mají vlastnosti různé typy, samotné keyof nestačí. Příšera má jméno jmeno (text) a životy zivoty (číslo). Funkce s parametrem klic: keyof Prisera vrací string | number: TypeScript neví, který klíč jí předáte, takže výsledek může být obojí. Generická funkce zachová přesný typ:
type Prisera = { jmeno: string; zivoty: number };
function ziskejVlastnost<K extends keyof Prisera>(prisera: Prisera, klic: K): Prisera[K] {
return prisera[klic];
}
const troll: Prisera = { jmeno: "Troll", zivoty: 80 };
console.log(ziskejVlastnost(troll, "jmeno").toUpperCase());
console.log(ziskejVlastnost(troll, "zivoty") - 30);Vypíše:
TROLL
50K extends keyof Prisera je omezení: K musí být jeden z klíčů. A Prisera[K] znamená „typ vlastnosti K v typu Prisera“. Ve volání ziskejVlastnost(troll, "jmeno") je K typ "jmeno", takže výsledek je typu Prisera["jmeno"], tedy string. Pro "zivoty" je to number. (Víc o takových typech se dozvíte v lekci 9.)
Jak psát:
Pokyny
Změňte typ parametru klic (pomocí keyof) tak, aby přijímal jen klíče typu Hrdina. TypeScript pak v jednom z volání najde chybně napsaný klíč. Opravte ho, aby program vypsal:
jmeno: Kira
uroven: 3Napište generickou funkci ziskejVlastnost<K extends keyof Hrdina>(hrdina: Hrdina, klic: K): Hrdina[K], která vrátí vlastnost hrdiny s klíčem klic.
Na konec přidejte tyto dva řádky. Fungují, jen když ziskejVlastnost vrací přesný typ: pro "povolani" text, pro "zlato" číslo.
console.log(ziskejVlastnost(kira, "povolani").toUpperCase());
console.log(ziskejVlastnost(kira, "zlato") + 50);Program vypíše:
jmeno: Kira
uroven: 3
HRANICAR
170Začněte programovat zdarma
8/9