Generické funkce

Tady je funkce z minulého cvičení, napsaná jednou pro všechny typy:

function prvni<T>(prvky: T[]): T | undefined {
    return prvky[0];
}

const jmena = ["Kira", "Bruno", "Lena"];
const ceny = [30, 12, 55];

console.log(prvni(jmena));
console.log(prvni(ceny));

Vypíše:

Kira
30

Nové je <T> za názvem funkce. Tím funkce deklaruje typový parametr jménem T. Obyčejný parametr zastupuje hodnotu, která může být při každém volání jiná. Typový parametr zastupuje typ, který může být při každém volání jiný. Ve zbytku funkce se T používá jako kterýkoli jiný typ: prvky: T[] je pole hodnot typu T a funkce vrací jednu hodnotu typu T (nebo undefined, k tomu se ještě dostaneme).

Při každém volání TypeScript za T dosadí typ podle argumentu. Ve volání prvni(jmena) je jmena typu string[], takže T je string a výsledek je typu string | undefined. Ve volání prvni(ceny) je T typ number. Funkci s typovým parametrem se říká generická funkce. Stejně jako verze s any funguje s každým polem, ale na rozdíl od ní TypeScript nezapomene, co do ní vstoupilo:

function prvni<T>(prvky: T[]): T | undefined {
    return prvky[0];
}

const jmena = ["Kira", "Bruno", "Lena"];
const ceny = [30, 12, 55];

const vudce = prvni(jmena);
if (vudce !== undefined) {
    console.log(vudce.toUpperCase());
}

const prvniCena = prvni(ceny);
if (prvniCena !== undefined) {
    console.log(prvniCena.toUpperCase());
}

TypeScript ohlásí:

main.ts(15,27): error TS2339: Property 'toUpperCase' does not exist on type 'number'.

vudce.toUpperCase() je v pořádku, protože vudce je text. prvniCena je ale číslo a TypeScript vám to řekne dřív, než program poběží.

Proč T | undefined? Prázdné pole žádný první prvek nemá, takže prvky[0] je undefined. TypeScript indexy v poli nekontroluje, a proto to řekneme v návratovém typu. Kdo funkci prvni zavolá, musí chybějící hodnotu ošetřit, stejně jako výsledek find v lekci 5: pomocí if (vudce !== undefined), vudce?.jmeno nebo ??. Bez kontroly TypeScript ohlásí 'vudce' is possibly 'undefined'. (TS18048). Jen k vypsání žádná kontrola potřeba není: console.log(prvni(jmena)) projde, protože console.log vypíše cokoli, i undefined.

Název T (z anglického type, typ) je jen zvyk. Fungoval by jakýkoli jiný, třeba function prvni<Prvek>(prvky: Prvek[]), obvykle se ale používají krátké názvy s velkým písmenem. A jako všechny typy i typové parametry za běhu programu zmizí. Výsledný JavaScript je jen function prvni(prvky) { return prvky[0]; }.

Typické chyby:

  • Chybí deklarace typového parametru: function prvni(prvky: T[]) skončí chybou Cannot find name 'T'. (TS2304). T existuje, teprve když za název funkce napíšete <T>.
  • Výsledek použitý bez kontroly na undefined (TS18048).

Pokyny

Nahraďte prvniHrdina a prvniLektvar jedinou generickou funkcí prvni<T>(prvky: T[]): T | undefined a použijte ji na obou místech. TypeScript vám pak oznámí, že vudce může být undefined: v šablonovém řetězci napište vudce?.jmeno. Program vypíše stejné řádky jako předtím.

Napište druhou generickou funkci, posledni<T>(prvky: T[]): T | undefined, která vrátí poslední prvek pole: prvky[prvky.length - 1].

Na konci programu pomocí posledni vypište poslední lektvar a jméno posledního hrdiny, aby program vypsal:

Vůdce: Kira
První lektvar: Léčivý lektvar
Poslední lektvar: Elixír
Poslední hrdina: Bruno

Začněte programovat zdarma

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

Nebo se registrujte pomocí:

2/9