Sjednocené typy

Ne každá hodnota má jen jeden typ. Když Kira splní úkol, dostane jako odměnu někdy zlato, tedy číslo jako 50, a někdy předmět, tedy text jako "Stříbrný meč". S typy, které zatím znáte, nemůže jedna proměnná obsahovat obojí:

let odmena = 50;
odmena = "Stříbrný meč";
main.ts(2,1): error TS2322: Type 'string' is not assignable to type 'number'.

Pro takové hodnoty má TypeScript sjednocené typy (anglicky union types). Napíšete několik typů a mezi ně svislou čáru |, kterou čtete jako „nebo“: number | string je „číslo, nebo text“.

let odmena: number | string = 50;
console.log(odmena);
odmena = "Stříbrný meč";
console.log(odmena);

Vypíše:

50
Stříbrný meč

Proměnná odmena teď může obsahovat číslo nebo text, ale pořád nic jiného. Když na konec přidáte řádek odmena = true;, TypeScript ohlásí:

main.ts(5,1): error TS2322: Type 'boolean' is not assignable to type 'string | number'.

V hlášce je sjednocení zapsané jako string | number, přestože v kódu stojí number | string. Na pořadí nezáleží, obojí je stejný typ. Sjednocení může mít i víc členů, třeba string | number | boolean. A jedno sjednocení už jste vlastně potkali: nepovinný parametr titul?: string má typ string | undefined.

Nejvíc se sjednocené typy hodí u parametrů. Tahle funkce přijme oba druhy odměny:

function ukazOdmenu(odmena: string | number): void {
    console.log(`Vaše odměna: ${odmena}`);
}

ukazOdmenu(50);
ukazOdmenu("Stříbrný meč");

Vypíše:

Vaše odměna: 50
Vaše odměna: Stříbrný meč

Co ale smí funkce s parametrem odmena dělat? Jen to, co funguje pro každý typ ve sjednocení. Vypsat jde číslo i text a obojí můžete vložit do šablonového řetězce. Metoda pro texty ale nejde:

function vykricOdmenu(odmena: string | number): string {
    return odmena.toUpperCase();
}
main.ts(2,19): error TS2339: Property 'toUpperCase' does not exist on type 'string | number'.
  Property 'toUpperCase' does not exist on type 'number'.

Tahle hláška má dva řádky. První říká, že sjednocení string | number nemá toUpperCase, a odsazený druhý řádek vysvětluje proč: nemá ji number. TypeScript nemůže vědět, jakou hodnotu funkce za běhu dostane. Kdyby dostala 50, JavaScript by skončil chybou TypeError: odmena.toUpperCase is not a function. TypeScript proto dovolí jen to, co je bezpečné pro oba typy. S počítáním je to stejné: i odmena * 2 je chyba, protože odměna může být text.

V dalším cvičení se naučíte zjistit, jakého typu hodnota je, abyste mohli s texty pracovat jako s texty a s čísly počítat.

Typická chyba: dvě svislé čáry místo jedné. V typech se píše jen jedna; let odmena: number || string = 50; není platný TypeScript a překladač se v něm ztratí:

main.ts(1,20): error TS1005: ',' expected.
main.ts(1,30): error TS1005: ';' expected.

Pokyny

Spusťte program: TypeScript nedovolí uložit do proměnné odmena text. Změňte typ proměnné odmena na sjednocení number a string, aby program vypsal:

Odměna: 50
Odměna: Stříbrný meč

Pod tento kód napište funkci oznam s jedním parametrem odmena typu string | number. Funkce vypíše Úkol splněn! Odměna: a za tím odměnu.

Zavolejte oznam dvakrát: s argumentem 120 a s argumentem "Starý klíč". Program pak vypíše:

Odměna: 50
Odměna: Stříbrný meč
Úkol splněn! Odměna: 120
Úkol splněn! Odměna: Starý klíč

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/10