Stavy úkolů

Rozlišené sjednocení se nehodí jen pro různé druhy věcí, ale i pro různé stavy jedné věci. Úkol v Kiřině deníku může být otevřený, splněný, nebo neúspěšný, a každý stav má vlastní data: splněný úkol má odměnu, neúspěšný důvod, proč se nepovedl, a otevřený nemá ani jedno:

type Ukol =
    | { stav: "otevreny"; nazev: string }
    | { stav: "splneny"; nazev: string; odmena: number }
    | { stav: "neuspesny"; nazev: string; duvod: string };

Značka se tu jmenuje stav, protože popisuje stav úkolu. Název je na vás; jen to musí být stejná vlastnost ve všech členech sjednocení a v každém s jiným literálovým typem. Takhle dlouhé sjednocení se lépe čte na víc řádcích. Pak můžete | napsat před každého člena, i před prvního: svislou čáru na úplném začátku TypeScript ignoruje.

Typ říká přesně to, co o každém úkolu víte. Odměnu má jen splněný úkol, a tak je čtení ukol.odmena bez kontroly chyba:

type Ukol =
    | { stav: "otevreny"; nazev: string }
    | { stav: "splneny"; nazev: string; odmena: number }
    | { stav: "neuspesny"; nazev: string; duvod: string };

const ukoly: Ukol[] = [
    { stav: "splneny", nazev: "Vlci v lese", odmena: 50 },
    { stav: "otevreny", nazev: "Ztracená koruna" },
    { stav: "neuspesny", nazev: "Záchrana mlynáře", duvod: "mlýn vyhořel" },
];

for (const ukol of ukoly) {
    console.log(`${ukol.nazev}: ${ukol.odmena} zlatých`);
}
main.ts(13,40): error TS2339: Property 'odmena' does not exist on type 'Ukol'.
  Property 'odmena' does not exist on type '{ stav: "otevreny"; nazev: string; }'.

Druhý řádek hlášky dokonce říká, který úkol odměnu nemá: otevřený. A úkol, který nedává smysl, nejde vůbec zapsat: const koruna: Ukol = { stav: "otevreny", nazev: "Ztracená koruna", odmena: 100 }; skončí chybou error TS2353: Object literal may only specify known properties, and 'odmena' does not exist in type '{ stav: "otevreny"; nazev: string; }'.

Vlastnost nazev mají všichni tři členové, takže ji můžete číst u každého úkolu. U ostatních nejdřív zkontrolujte stav:

for (const ukol of ukoly) {
    if (ukol.stav === "splneny") {
        console.log(`${ukol.nazev}: ${ukol.odmena} zlatých`);
    } else {
        console.log(`${ukol.nazev}: bez odměny`);
    }
}

Vypíše:

Vlci v lese: 50 zlatých
Ztracená koruna: bez odměny
Záchrana mlynáře: bez odměny

Porovnejte to s jedním typem s nepovinnými vlastnostmi, { stav: string; nazev: string; odmena?: number; duvod?: string }. Ten dovolí otevřený úkol s odměnou, splněný úkol bez ní, a dokonce stav "slpneny". Právě o takových typech je další cvičení.

Pokyny

Spusťte program: třetí úkol do typu nezapadá. Přidejte do sjednocení Ukol třetího člena: neúspěšný úkol se stav: "neuspesny", s vlastností nazev a s vlastností duvod (obě jsou texty).

Napište funkci popisUkolu s parametrem ukol typu Ukol, která vrátí popis úkolu. Použijte switch podle ukol.stav (s kontrolou úplnosti ve větvi default, ať si ji procvičíte) a vypište popis každého úkolu. Program pak vypíše:

Vlci v lese: splněno, +50 zlatých
Ztracená koruna: probíhá
Záchrana mlynáře: nezdar (mlýn vyhořel)
Skřetí most: splněno, +30 zlatých

Sečtěte odměny splněných úkolů a na konci vypište součet:

Vlci v lese: splněno, +50 zlatých
Ztracená koruna: probíhá
Záchrana mlynáře: nezdar (mlýn vyhořel)
Skřetí most: splněno, +30 zlatých
Odměny celkem: 80 zlatých

Začněte programovat zdarma

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

Nebo se registrujte pomocí:

6/8