typeof guard în TypeScript

Narrowing și type guards TypeScript 1.4

Verificarea typeof x === "string" (sau "number", "boolean"...) restrânge tipul la primitivul respectiv.

Sintaxă
if (typeof x === "string") { ... }
// valori: "string" "number" "bigint" "boolean" "symbol" "undefined" "object" "function"

Ce face typeof guard

Operatorul typeof din JavaScript returnează la rulare un text care spune ce fel de valoare ai: "string", "number", "bigint", "boolean", "symbol", "undefined", "object" sau "function". Când îl compari cu una dintre aceste valori, TypeScript restrânge tipul variabilei în ramura respectivă.

Merge cu ===, !==, ==, != și în switch (typeof x). TypeScript știe lista valorilor posibile și dă eroare dacă scrii greșit ("strng").

Două capcane din JavaScript: typeof null este "object", iar tablourile sunt tot "object" (folosește Array.isArray). Nu confunda acest typeof cu typeof de tip, care există doar la compilare.

Exemple

Exemplul 1: Formatarea unei valori din formular

function laNumar(x: string | number | boolean): number {
    if (typeof x === "number") return x;
    if (typeof x === "boolean") return x ? 1 : 0;
    return Number.parseFloat(x.replace(",", "."));     // aici x este string
}

console.log(laNumar(7), laNumar(true), laNumar("9,75"));

Rezultat

7 1 9.75

Exemplul 2: switch pe typeof și capcana lui null

function tip(x: unknown): string {
    switch (typeof x) {
        case "string": return `text (${x.length})`;
        case "number": return `număr (${x})`;
        case "function": return "funcție";
        case "object": return x === null ? "null" : Array.isArray(x) ? "tablou" : "obiect";
        default: return typeof x;
    }
}

for (const v of ["Ana", 42, () => 1, null, [1, 2], { a: 1 }, undefined, 10n]) {
    console.log(tip(v));
}

Rezultat

text (3)
număr (42)
funcție
null
tablou
obiect
undefined
bigint

Exemplul 3: Valoare scrisă greșit

function f(x: string | number) {
    if (typeof x === "strng") {
        console.log(x);
    }
}
f("a");

Eroarea afișată de tsc

exemplu.mts(2,9): error TS2367: This comparison appears to be unintentional because the types '"string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"strng"' have no overlap.

Greșeli frecvente

  • Verifici typeof x === "object" și folosești imediat x.proprietate. x poate fi null; tsc spune ‘x’ is possibly ‘null’.
  • Folosești typeof x === "array". Nu există; folosește Array.isArray(x).

Comenzi înrudite

  • type guards: Verificări la rulare pe care TypeScript le înțelege și după care știe tipul exact al unei valori.
  • narrowing: TypeScript urmărește verificările din cod (if, switch, return) și restrânge tipul unei variabile în fiecare ramură.
  • typeof (tip): În poziție de tip, typeof x dă tipul variabilei sau funcției x, ca să nu-l scrii de mână.
  • instanceof guard: x instanceof Clasa verifică dacă obiectul a fost creat din clasă și restrânge tipul la acea clasă.
  • unknown: Tipul sigur pentru valori necunoscute: acceptă orice, dar nu poți folosi valoarea până nu verifici ce tip are.