Proč generika

Některým funkcím je jedno, co je v poli. Funkce, která vrátí první prvek, funguje stejně pro jména, ceny i hrdiny. V JavaScriptu byste ji napsali jednou:

function prvni(prvky) {
    return prvky[0];
}

V TypeScriptu potřebuje parametr typ, jinak dostanete chybu Parameter 'prvky' implicitly has an 'any' type. (TS7006). Jaký typ to ale má být, když v poli může být cokoli? Vyzkoušejme možnosti, které znáte.

Možnost 1: any. Parametr typu any[] přijme jakékoli pole a funkce vrací any:

type Hrdina = { jmeno: string; zivoty: number };

// Vrátí první prvek pole
function prvni(prvky: any[]): any {
    return prvky[0];
}

const hrdinove: Hrdina[] = [
    { jmeno: "Kira", zivoty: 50 },
    { jmeno: "Bruno", zivoty: 70 },
];
const lektvary: string[] = ["Léčivý lektvar", "Lektvar many"];

const vudce = prvni(hrdinove);
console.log(`Vůdce: ${vudce.jmeno}, životy ${vudce.zivot}`);

const lektvar = prvni(lektvary);
console.log(lektvar.toUppercase());

Vypíše:

Vůdce: Kira, životy undefined
TypeError: lektvar.toUppercase is not a function

TypeScript neohlásil ani jeden z těch dvou překlepů. Neví totiž, že vudce je hrdina a lektvar text: obojí je any a u any se nic nekontroluje. Chyby z JavaScriptu jsou zpátky: místo čísla undefined a pád programu za běhu.

Možnost 2: unknown. V lekci 5 jste poznali bezpečnou obdobu any. S unknown vám TypeScript výsledek nedovolí použít, dokud jeho typ nezúžíte:

function prvni(prvky: unknown[]): unknown {
    return prvky[0];
}

const jmena = ["Kira", "Bruno", "Lena"];
const vudce = prvni(jmena);
console.log(vudce.toUpperCase());

TypeScript ohlásí:

main.ts(7,13): error TS18046: 'vudce' is of type 'unknown'.

Je to bezpečné, ale moc vám to nepomůže. Vy víte, že první prvek pole jmena je text, jenže TypeScript to cestou přes funkci zapomněl. Po každém volání byste museli kontrolovat typeof vudce === "string".

Možnost 3: pro každý typ zvláštní funkce.

function prvniJmeno(jmena: string[]): string {
    return jmena[0];
}

function prvniHrdina(hrdinove: Hrdina[]): Hrdina {
    return hrdinove[0];
}

Teď TypeScript kontroluje všechno: prvniHrdina(hrdinove).zivot je chyba. Obě funkce ale mají stejné tělo a každý další typ potřebuje další kopii: prvniLektvar, prvniUkol, prvniPrisera…

Chtěli bychom jedinou funkci, která říká: „Ať mají prvky jakýkoli typ, vrátím prvek stejného typu.“ Přesně tohle v TypeScriptu umějí generika, téma této lekce. Svou první generickou funkci napíšete v příštím cvičení. Nejdřív si ale v editoru vyzkoušejte možnost 3 a uvidíte, kam vede.

Pokyny

Spusťte program: vypíše životy undefined a léčí undefined a TypeScript nic nenamítá. Napište funkci prvniHrdina(hrdinove: Hrdina[]): Hrdina se stejným tělem, jako má prvni, a použijte ji pro vudce místo prvni. TypeScript pak najde překlep na řádku s vudce.zivot. Opravte ho.

Totéž udělejte pro lektvary: napište prvniLektvar(lektvary: Lektvar[]): Lektvar, použijte ji pro lektvar a opravte chybu, kterou TypeScript najde. Program pak vypíše:

Vůdce: Kira, životy 50
Lektvar: Léčivý lektvar, léčí 20

Teď TypeScript kontroluje oba řádky. Máte ale dvě funkce se stejným tělem a další typ by potřeboval třetí. V příštím cvičení je všechny nahradí jediná funkce.

Začněte programovat zdarma

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

Nebo se registrujte pomocí:

1/9