Omezení
Napišme generickou funkci, která najde nejsilnějšího z čehokoli, co má sílu (sila): z hrdinů, příšer i kouzel.
function nejsilnejsi<T>(veci: T[]): T {
let nejlepsi = veci[0];
for (const vec of veci) {
if (vec.sila > nejlepsi.sila) {
nejlepsi = vec;
}
}
return nejlepsi;
}TypeScript ohlásí:
main.ts(4,17): error TS2339: Property 'sila' does not exist on type 'T'.
main.ts(4,33): error TS2339: Property 'sila' does not exist on type 'T'.TypeScript má pravdu: T může být jakýkoli typ, takže by někdo mohl nejsilnejsi zavolat s polem čísel nebo textů, a ty žádnou vlastnost sila nemají. Musíte říct, které typy jsou dovolené. K tomu slouží omezení:
type Hrdina = { jmeno: string; sila: number };
type Prisera = { druh: string; sila: number; korist: string };
function nejsilnejsi<T extends { sila: number }>(veci: T[]): T {
let nejlepsi = veci[0];
for (const vec of veci) {
if (vec.sila > nejlepsi.sila) {
nejlepsi = vec;
}
}
return nejlepsi;
}
const hrdinove: Hrdina[] = [
{ jmeno: "Kira", sila: 7 },
{ jmeno: "Bruno", sila: 9 },
];
const prisery: Prisera[] = [
{ druh: "skret", sila: 3, korist: "Rezavá dýka" },
{ druh: "troll", sila: 8, korist: "Velký kyj" },
];
console.log(nejsilnejsi(hrdinove).jmeno);
console.log(nejsilnejsi(prisery).korist);Vypíše:
Bruno
Velký kyjT extends { sila: number } znamená: T smí být jakýkoli typ, který má vlastnost sila typu číslo (a cokoli dalšího k tomu). Je to stejné slovo jako v interface Boss extends Prisera z lekce 4: „odpovídá tomuto tvaru a může mít i víc“. Uvnitř funkce už je vec.sila dovolené. A výsledek si zachová celý svůj typ: pro hrdiny vrátí nejsilnejsi typ Hrdina, takže funguje .jmeno, pro příšery typ Prisera i s její kořistí.
Volání s polem, které omezení nesplňuje, je chyba. Přidejte na konec programu tyto dva řádky:
const jmena = ["Kira", "Bruno"];
console.log(nejsilnejsi(jmena));TypeScript ohlásí:
main.ts(26,25): error TS2345: Argument of type 'string[]' is not assignable to parameter of type '{ sila: number; }[]'.
Type 'string' is not assignable to type '{ sila: number; }'.Proč ne bez generik? Funkce nejsilnejsi(veci: { sila: number }[]): { sila: number } přijme stejná pole, jenže vrátí jen { sila: number }. TypeScript zapomene, že šlo o hrdinu, a nejsilnejsi(hrdinove).jmeno skončí chybou Property 'jmeno' does not exist on type '{ sila: number; }'. (TS2339). S omezením máte obojí: omezení říká, co funkce potřebuje, a typový parametr zachová, co má ten, kdo ji volá.
Omezením může být jakýkoli typ, i pojmenovaný: s type Silny = { sila: number }; napíšete <T extends Silny>.
Jak psát:
Pokyny
Napište generickou funkci najdiPodleJmena<T extends { jmeno: string }>(veci: T[], jmeno: string): T | undefined. Vrátí první prvek, jehož vlastnost jmeno se rovná parametru jmeno, nebo undefined, když takový není; použijte find.
Pomocí najdiPodleJmena vypište Brunovo povolani, cenu (cena) stříbrného meče a to, co funkce najde v obchodě pro jméno "Dračí vejce". (Výsledky můžou být undefined, takže použijte ?..) Program vypíše:
valecnik
120
undefinedZačněte programovat zdarma
7/9