Sjednocení literálů

Spousta hodnot ve hře pochází z krátkého, pevně daného seznamu. Hrdina je válečník, mág, nebo hraničář; na mapě jdete na sever, na jih, na východ, nebo na západ. Jako text je taková hodnota string, jenže string může být jakýkoli text, i s překlepem:

function pocatecniZivoty(povolani: string): number {
    if (povolani === "valecnik") {
        return 120;
    } else if (povolani === "mag") {
        return 70;
    } else {
        return 90;
    }
}

console.log(pocatecniZivoty("valecnki"));

Program vypíše 90, tedy životy hraničáře, protože "valecnki" není "valecnik". Žádná chyba, jen špatné číslo někde ve hře, a příčinu pak můžete hledat hodně dlouho.

V lekci Základní typy jste viděli, že literálový typ, třeba "tezka", dovoluje přesně jednu hodnotu. Pomocí | můžete několik literálových typů spojit do sjednocení literálů a pojmenovat ho pomocí type:

type Povolani = "valecnik" | "mag" | "hranicar";

Povolani je jeden z těchto tří textů a nic jiného. Dejte tenhle řádek na začátek programu výše, změňte parametr na povolani: Povolani a TypeScript zkontroluje každé volání:

main.ts(13,29): error TS2345: Argument of type '"valecnki"' is not assignable to parameter of type 'Povolani'.

Uvozovky uvnitř uvozovek znamenají přesně text "valecnki", jak to znáte u literálových typů. Stejná ochrana funguje všude, kde typ použijete. U proměnné vám TypeScript dokonce napoví, co jste nejspíš mysleli:

type Povolani = "valecnik" | "mag" | "hranicar";

let zvolene: Povolani = "valecnki";
main.ts(3,5): error TS2820: Type '"valecnki"' is not assignable to type 'Povolani'. Did you mean '"valecnik"'?

A kontroluje i porovnání. Kdyby byl překlep ve funkci, v if (povolani === "valecnki"), TypeScript by ohlásil:

main.ts(4,9): error TS2367: This comparison appears to be unintentional because the types 'Povolani' and '"valecnki"' have no overlap.

„No overlap“ znamená, že se typy nepřekrývají: žádná hodnota není zároveň Povolani i text "valecnki", takže porovnání nemůže nikdy platit.

Jedna věc vás možná překvapí. Když je povolání v proměnné let bez typu, je volání chyba, přestože "mag" povolání je. S těmito dvěma řádky pod funkcí:

let volba = "mag";
console.log(pocatecniZivoty(volba));
main.ts(14,29): error TS2345: Argument of type 'string' is not assignable to parameter of type 'Povolani'.

TypeScript odvodil pro proměnnou volba typ string, stejně jako pro každé let s textem: později do ní můžete uložit jakýkoli jiný text. Buď proměnné typ dejte, let volba: Povolani = "mag";, nebo použijte const: typ const volba = "mag" je literálový typ "mag", a ten se do parametru hodí.

Poznámka do budoucna: v jiných jazycích a ve starším kódu v TypeScriptu můžete takové seznamy vidět zapsané jako enum (výčtový typ), třeba enum Smer { Sever, Jih }. Na rozdíl od ostatních typů enum po odstranění typů nezmizí: stane se z něj kus kódu v JavaScriptu. Proto ho nastavení tohoto webu nedovoluje:

main.ts(1,6): error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.

V novějším kódu v TypeScriptu ho často nahrazují sjednocení literálů, jaká teď píšete i vy.

Pokyny

Program třikrát vypíše 90, ale válečník má začínat se 120 životy a mág se 70. Nad funkcí vytvořte typ Povolani pro tři povolání "valecnik", "mag" a "hranicar" a použijte ho jako typ parametru povolani. TypeScript pak najde dva překlepy: opravte je, aby program vypsal:

120
70
90

Pod volání vytvořte typ Hrdina pro objekt s vlastnostmi jmeno (text) a povolani typu Povolani. Pak vytvořte konstantu kira typu Hrdina: jmenuje se "Kira" a její povolání je "hranicar".

Vypište řádek o Kiře pomocí jejích vlastností a funkce pocatecniZivoty. Program pak vypíše:

120
70
90
Kira začíná s 90 životy

Začněte programovat zdarma

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

Nebo se registrujte pomocí:

3/10