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

T 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>.

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
undefined

Začněte programovat zdarma

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

Nebo se registrujte pomocí:

7/9