Pick a Omit

Cech si vede seznam svých členů. Každý člen má id, číslo, které od cechu dostane, když do něj vstoupí:

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

interface Hrdina {
    id: number;
    jmeno: string;
    povolani: Povolani;
    uroven: number;
}

Funkce, která přidá nového člena, dostane hrdinu bez id, protože id přiděluje cech. Mohli byste napsat druhé rozhraní se zbylými třemi vlastnostmi, ale pak byste je museli ručně udržovat ve shodě. Místo toho napište Omit<Hrdina, "id">: typ Hrdina bez vlastnosti id. Druhý typový argument je název vlastnosti, jako literálový typ v uvozovkách. Když chcete vynechat víc vlastností, napište sjednocení: Omit<Hrdina, "id" | "uroven">.

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

interface Hrdina {
    id: number;
    jmeno: string;
    povolani: Povolani;
    uroven: number;
}

let dalsiId = 1;

function pridejClena(novyHrdina: Omit<Hrdina, "id">): Hrdina {
    const hrdina: Hrdina = { id: dalsiId, ...novyHrdina };
    dalsiId++;
    return hrdina;
}

console.log(pridejClena({ jmeno: "Kira", povolani: "hranicar", uroven: 3 }));
console.log(pridejClena({ jmeno: "Bruno", povolani: "valecnik", uroven: 5 }));

Vypíše:

{ id: 1, jmeno: "Kira", povolani: "hranicar", uroven: 3 }
{ id: 2, jmeno: "Bruno", povolani: "valecnik", uroven: 5 }

Nového hrdinu poskládá spread z předchozího cvičení: nejdřív id, pak všechny vlastnosti objektu novyHrdina. Výsledek má všechny čtyři vlastnosti, takže je to Hrdina. A při volání TypeScript porovná argument s typem Omit<Hrdina, "id">: id je teď chyba, a stejně tak chybějící vlastnost:

pridejClena({ id: 7, jmeno: "Kira", povolani: "hranicar", uroven: 3 });
pridejClena({ jmeno: "Lena", povolani: "mag" });
main.ts(18,15): error TS2353: Object literal may only specify known properties, and 'id' does not exist in type 'Omit<Hrdina, "id">'.
main.ts(19,13): error TS2741: Property 'uroven' is missing in type '{ jmeno: string; povolani: "mag"; }' but required in type 'Omit<Hrdina, "id">'.

Pick funguje obráceně: Pick<Hrdina, "jmeno" | "uroven"> si nechá jen vyjmenované vlastnosti, takže je to { jmeno: string; uroven: number }. Hodí se pro funkci, která z objektu potřebuje jen část:

function odznak(hrdina: Pick<Hrdina, "jmeno" | "uroven">): string {
    return `${hrdina.jmeno}, úroveň ${hrdina.uroven}`;
}

Můžete jí předat celého hrdinu typu Hrdina: má jméno i úroveň a na zbytek se funkce nedívá. Nebo menší objekt, třeba { jmeno: "Lena", uroven: 1 }. Uvnitř funkce ale nic jiného než jmeno a uroven není. hrdina.povolani by byla chyba: Property 'povolani' does not exist on type 'Pick<Hrdina, "jmeno" | "uroven">'.

Typické chyby:

  • Překlep v Pick TypeScript odhalí, protože názvy musí být klíče typu Hrdina. Je to omezení pomocí keyof, jako v lekci o generikách:
    main.ts(10,38): error TS2344: Type '"jmeno" | "urovne"' does not satisfy the constraint 'keyof Hrdina'.
      Type '"urovne"' is not assignable to type 'keyof Hrdina'. Did you mean '"uroven"'?
  • Překlep v Omit neodhalí! Omit<Hrdina, "idd"> nic nevynechá, id zůstane a žádná chyba se neohlásí. Názvy v Omit si proto pečlivě zkontrolujte.
  • Několik názvů je jeden typový argument, sjednocení: Pick<Hrdina, "jmeno" | "uroven">. S čárkou, Pick<Hrdina, "jmeno", "uroven">, TypeScript ohlásí Generic type 'Pick' requires 2 type argument(s). (generický typ Pick potřebuje dva typové argumenty).

Pokyny

Pod komentář // Přidá nového člena napište funkci pridejClena(novyHrdina: Omit<Hrdina, "id">): Hrdina. Ta vytvoří hrdinu s id z proměnné dalsiId, zvýší dalsiId o jedna, přidá hrdinu do pole cech pomocí push a vrátí ho.

Pod funkcí přidejte dva členy a vypište, co pridejClena vrátí: Kiru, hraničářku úrovně 3, a Bruna, válečníka úrovně 5:

{ id: 1, jmeno: "Kira", povolani: "hranicar", uroven: 3 }
{ id: 2, jmeno: "Bruno", povolani: "valecnik", uroven: 5 }

Pod to napište funkci popisClena(hrdina: Pick<Hrdina, "jmeno" | "uroven">): string, která vrátí jméno a úroveň takto: Kira (úroveň 3).

Pod ni v cyklu for...of vypište, co popisClena() vrátí pro každého člena pole cech. Pak vypište ještě popisClena({ jmeno: "Lena", uroven: 1 }): Lena v cechu zatím není, ale funkce potřebuje jen jméno a úroveň. Program končí takto:

Kira (úroveň 3)
Bruno (úroveň 5)
Lena (úroveň 1)

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