type guards în TypeScript

Narrowing și type guards TypeScript 1.4

Verificări la rulare pe care TypeScript le înțelege și după care știe tipul exact al unei valori.

Sintaxă
typeof x === "string"
x instanceof Date
"proprietate" in x
function esteElev(x: unknown): x is Elev { ... }

Ce face type guards

Un type guard este o expresie care verifică la rulare ce fel de valoare ai și din care TypeScript trage o concluzie despre tip. Fără ele, nu ai putea folosi în siguranță un union sau o valoare unknown.

Feluri de type guards: typeof pentru tipurile primitive, instanceof pentru obiecte create din clase, in pentru a verifica existența unei proprietăți, comparații cu valori literale (pe o proprietate comună, ca în discriminated unions), Array.isArray și funcțiile tale proprii, cu predicat de tip (x is Tip) sau asserts.

Interfețele și aliasurile type nu există la rulare, deci nu poți scrie x instanceof Elev pentru o interfață. Pentru ele scrii un predicat care verifică proprietățile.

Exemple

Exemplul 1: Patru type guards în aceeași funcție

class Data2 {
    constructor(public an: number, public luna: number) {}
}
interface Elev {
    nume: string;
}
type Valoare = string | number | Date | Data2 | Elev;

function format(v: Valoare): string {
    if (typeof v === "string") return `„${v}”`;
    if (typeof v === "number") return v.toLocaleString("ro-RO");
    if (v instanceof Date) return v.toISOString().slice(0, 10);
    if (v instanceof Data2) return `${v.luna}/${v.an}`;
    return `elevul ${v.nume}`;
}

const valori: Valoare[] = ["Iași", 1234567.5, new Date(Date.UTC(2026, 9, 19)), new Data2(2026, 10), { nume: "Ana" }];
for (const v of valori) console.log(format(v));

Rezultat

„Iași”
1.234.567,5
2026-10-19
10/2026
elevul Ana

Exemplul 2: Predicat propriu pentru o interfață

interface Elev {
    nume: string;
    nota: number;
}

function esteElev(x: unknown): x is Elev {
    return typeof x === "object" && x !== null &&
        typeof (x as Elev).nume === "string" && typeof (x as Elev).nota === "number";
}

const date: unknown[] = JSON.parse('[{"nume":"Ana","nota":10},{"nume":"Mihai"},"text"]');
const elevi = date.filter(esteElev);      // Elev[]
console.log(elevi.map((e) => `${e.nume}: ${e.nota}`));

Rezultat

[ 'Ana: 10' ]

Greșeli frecvente

  • Scrii instanceof cu o interfață: tsc dă ‘Elev’ only refers to a type, but is being used as a value here.
  • Folosești typeof x === "object" și uiți că typeof null este tot "object". Verifică și x !== null.

Comenzi înrudite

  • narrowing: TypeScript urmărește verificările din cod (if, switch, return) și restrânge tipul unei variabile în fiecare ramură.
  • typeof guard: Verificarea typeof x === „string” (sau „number”, „boolean”…) restrânge tipul la primitivul respectiv.
  • instanceof guard: x instanceof Clasa verifică dacă obiectul a fost creat din clasă și restrânge tipul la acea clasă.
  • in guard: „cheie” in x verifică dacă obiectul are proprietatea și restrânge union-ul la variantele care o au.
  • predicat de tip (is): O funcție cu rezultatul x is Tip spune compilatorului că, dacă returnează true, x are tipul Tip.
  • asserts: O funcție asserts aruncă o eroare dacă verificarea eșuează; după apel, TypeScript știe că tipul este cel cerut.