Pole jen pro čtení

Funkce nedostane vlastní kopii pole, ale totéž pole, které má volající. Může tedy změnit pole, které jí nepatří. Tahle funkce má spočítat lektvary ve vaku a spočítá je správně. Podívejte se ale, jak vak vypadá potom:

const vak = ["Lektvar", "Lano", "Lektvar"];

function spocitejLektvary(predmety: string[]): number {
    let pocet = 0;
    while (predmety.length > 0) {
        if (predmety.pop() === "Lektvar") {
            pocet++;
        }
    }
    return pocet;
}

console.log(spocitejLektvary(vak));
console.log(vak);

Vypíše:

2
[]

pop() z pole odebere poslední prvek, takže po spočítání je vak prázdný. Ve velkém programu se taková chyba hledá těžko: vak se vyprázdní ve funkci, která na první pohled jen počítá. TypeScript tomu dokáže zabránit. Napište před typ pole readonly:

function spocitejLektvary(predmety: readonly string[]): number {
main.ts(6,22): error TS2339: Property 'pop' does not exist on type 'readonly string[]'.

readonly string[] je pole, které můžete číst, ale ne měnit. Čtení prvku, length, for...of, includes, find, map i filter fungují (map a filter vytvářejí nové pole). Chybí ale push i pop a do prvku nejde přiřadit: predmety[0] = "Meč" skončí chybou Index signature in type 'readonly string[]' only permits reading. (prvky tohoto typu jde jen číst). V parametru je readonly slib, který volající vidí hned v prvním řádku funkce: tahle funkce pole jen čte.

Stejný typ jde napsat i jako ReadonlyArray<string>, podobně jako se string[] dá napsat jako Array<string>. V chybových hláškách TypeScript píše readonly string[].

Obyčejné pole do parametru readonly předat můžete: funkce ho jen čte. Obráceně to nejde. Pole jen pro čtení, třeba seznam vytvořený pomocí as const v lekci Modelování dat, do parametru typu string[] nepředáte, protože taková funkce by ho mohla změnit:

const vsechnaPovolani = ["valecnik", "mag", "hranicar"] as const;

function vypisVsechna(nazvy: string[]): void {
    for (const nazev of nazvy) {
        console.log(nazev);
    }
}

vypisVsechna(vsechnaPovolani);
main.ts(9,14): error TS4104: The type 'readonly ["valecnik", "mag", "hranicar"]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.

Funkce, která pole jen čte, má proto brát pole readonly: přijme pak obojí. A když má vrátit pole s něčím navíc, vytvoří nové pomocí spreadu: [...predmety, "Stará mapa"].

Pro objekty je tu pomocný typ Readonly<Hrdina>: Hrdina, ve kterém je každá vlastnost jen pro čtení. Je to jako napsat readonly před každou vlastnost, jako v lekci o typech objektů, ale jen tam, kde ho použijete. Parametr hrdina: Readonly<Hrdina> říká, že funkce hrdinu nemění, a hrdina.zivoty = 0 uvnitř ní skončí chybou Cannot assign to 'zivoty' because it is a read-only property. Stejně jako ostatní typy kontroluje readonly jen TypeScript. JavaScript, který se spustí, o něm nic neví.

Typické chyby:

  • readonly patří jen před typy s []. readonly Array<string> skončí chybou 'readonly' type modifier is only permitted on array and tuple literal types. Napište readonly string[], nebo ReadonlyArray<string>.
  • Funkce s návratovým typem string[] vrátí přímo svůj parametr: The type 'readonly string[]' is 'readonly' and cannot be assigned to the mutable type 'string[]'. Vraťte nové pole.

Pokyny

Funkce sPredmetem má vrátit nový seznam, ale mění ten, který dostane. Změňte typ jejího parametru predmety na readonly string[] a spusťte program: TypeScript ohlásí řádek s push. Tělo funkce nahraďte příkazem return [...predmety, predmet];.

Pod funkcemi vypište sPredmetem(inventar, "Stará mapa") a potom inventar. Inventář se nezměnil:

["Léčivý lektvar", "Lano", "Pochodeň", "Stará mapa"]
["Léčivý lektvar", "Lano", "Pochodeň"]

Ani funkce textZivotu nemá hrdinu měnit. Změňte typ jejího parametru na Readonly<Hrdina> a spusťte program. TypeScript ve funkci najde řádek, který hrdinu přece jen mění. Opravte chybu: jedno = hodnotu přiřazuje, a vy chcete porovnávat.

Pod ostatní řádky vypište textZivotu(kira):

Kira: 34/50

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