null a undefined
Někdy hodnota chybí: hrdina nemá mazlíčka, truhla je prázdná, hledání nic nenajde. JavaScript má pro „nic“ dvě hodnoty. undefined dostanete z chybějící vlastnosti nebo argumentu. null programátoři ukládají schválně, když chtějí říct „tady nic není“. S null jste se setkali v kurzu JavaScriptu: vracela ho metoda querySelector(), když nenašla žádný prvek, a další řádek pak skončil chybou TypeError: Cannot read properties of null. Tahle chyba patří k nejčastějším chybám v programech v JavaScriptu.
V TypeScriptu mají null a undefined vlastní typy a ostatní typy je neobsahují. Do proměnné typu string tak null uložit nemůžete:
let cil: string = null;main.ts(1,5): error TS2322: Type 'null' is not assignable to type 'string'.Když hodnota může chybět, řeknete to sjednocením: Mazlicek | null je „mazlíček, nebo nic“. TypeScript pak dohlédne na to, abyste hodnotu před použitím zkontrolovali:
type Mazlicek = { jmeno: string; zvire: string };
type Hrdina = { jmeno: string; mazlicek: Mazlicek | null };
function popisMazlicka(hrdina: Hrdina): string {
return `${hrdina.jmeno}: mazlíček ${hrdina.mazlicek.jmeno} (${hrdina.mazlicek.zvire})`;
}main.ts(5,41): error TS18047: 'hrdina.mazlicek' is possibly 'null'.
main.ts(5,67): error TS18047: 'hrdina.mazlicek' is possibly 'null'.„Possibly null“ znamená „možná null“: až funkce poběží, může být v hrdina.mazlicek hodnota null a čtení hrdina.mazlicek.jmeno by pak skončilo chybou TypeError: Cannot read properties of null (reading 'jmeno'). V JavaScriptu byste na to přišli, až by program spadl, a to jen v případě, že by někdo funkci zavolal pro hrdinu bez mazlíčka. TypeScript vám to řekne dřív, než program spustíte.
Opravou je kontrola a ta typ zúží stejně jako typeof:
type Mazlicek = { jmeno: string; zvire: string };
type Hrdina = { jmeno: string; mazlicek: Mazlicek | null };
function popisMazlicka(hrdina: Hrdina): string {
if (hrdina.mazlicek === null) {
return `${hrdina.jmeno}: žádný mazlíček`;
}
return `${hrdina.jmeno}: mazlíček ${hrdina.mazlicek.jmeno} (${hrdina.mazlicek.zvire})`;
}
const kira: Hrdina = { jmeno: "Kira", mazlicek: { jmeno: "Pip", zvire: "sova" } };
const bruno: Hrdina = { jmeno: "Bruno", mazlicek: null };
console.log(popisMazlicka(kira));
console.log(popisMazlicka(bruno));Vypíše:
Kira: mazlíček Pip (sova)
Bruno: žádný mazlíčekPod podmínkou s return je hrdina.mazlicek typu Mazlicek. Kontrolu můžete napsat i obráceně, if (hrdina.mazlicek !== null) { … }; pak je hrdina.mazlicek typu Mazlicek uvnitř složených závorek. Jak vidíte, zužování funguje i u vlastností, nejen u proměnných a parametrů.
mazlicek: Mazlicek | null není totéž co nepovinná vlastnost mazlicek?: Mazlicek. Tady musí být vlastnost uvedená vždycky a hrdina bez mazlíčka má mazlicek: null. Nepovinnou vlastnost můžete vynechat a její typ je Mazlicek | undefined: chybová hláška pak říká is possibly 'undefined' (TS18048) a hodnotu kontrolujete pomocí !== undefined.
Typická chyba: kontrola na špatné „nic“. if (hrdina.mazlicek !== undefined) nevyloučí null, takže u typu Mazlicek | null TypeScript dál hlásí 'hrdina.mazlicek' is possibly 'null'. Kontrolujte tu hodnotu, kterou typ obsahuje.
Jak psát:
Pokyny
Spusťte program a opravte chyby pomocí kontroly: když je cil null, funkce vypíše Není na koho útočit a nic dalšího neudělá. Program pak vypíše:
Vlk má ještě 18 životů
Není na koho útočitKira si zatím nevybrala nový cíl. Pod volání vytvořte proměnnou (let) aktualniCil typu Prisera | null s hodnotou null a zavolejte utok(aktualniCil, 5).
Pak Kira zahlédne skřeta. Uložte do proměnné aktualniCil objekt { jmeno: "Skřet", zivoty: 20 } a znovu zavolejte utok(aktualniCil, 5). Program pak vypíše:
Vlk má ještě 18 životů
Není na koho útočit
Není na koho útočit
Skřet má ještě 15 životůZačněte programovat zdarma
4/10