Ce face in guard
Operatorul in din JavaScript verifică dacă un obiect are o proprietate (proprie sau moștenită). Când x este un union de obiecte, "zboara" in x restrânge tipul la variantele care au proprietatea zboara, iar în else rămân celelalte.
Este potrivit pentru union-uri de obiecte care nu au o proprietate comună de tip literal (pentru acestea, discriminated unions sunt mai clare). Din TypeScript 4.9, in funcționează și pe valori object sau unknown deja verificate: după "nume" in x, tipul devine object & Record<"nume", unknown>.
Atenție: o proprietate opțională (email?) poate apărea în ambele ramuri, iar in spune doar că proprietatea există, nu și ce tip are valoarea ei.
Exemple
Exemplul 1: Union de obiecte fără proprietate comună
interface Card {
numar: string;
expira: string;
}
interface Transfer {
iban: string;
}
type Plata = Card | Transfer;
function descrie(p: Plata): string {
if ("iban" in p) return `transfer în ${p.iban.slice(0, 4)}…${p.iban.slice(-4)}`;
return `card ****${p.numar.slice(-4)}, expiră ${p.expira}`;
}
console.log(descrie({ numar: "4111111111111111", expira: "08/28" }));
console.log(descrie({ iban: "RO49AAAA1B31007593840000" }));
Rezultat
card ****1111, expiră 08/28
transfer în RO49…0000
Exemplul 2: Verificarea unui obiect unknown
function nume(x: unknown): string {
if (typeof x === "object" && x !== null && "nume" in x && typeof x.nume === "string") {
return x.nume;
}
return "(fără nume)";
}
console.log(nume({ nume: "Ana", oras: "Iași" }));
console.log(nume({ nume: 42 }));
console.log(nume("Ana"));
Rezultat
Ana
(fără nume)
(fără nume)
Exemplul 3: Proprietate care nu există în nicio variantă
După ce "iban" in p a eliminat Transfer, în else a rămas doar Card, care nu are iban.
interface Card {
numar: string;
}
interface Transfer {
iban: string;
}
function f(p: Card | Transfer) {
if ("iban" in p) console.log(p.iban);
else console.log(p.iban);
}
f({ numar: "1" });
Eroarea afișată de tsc
exemplu.mts(9,24): error TS2339: Property 'iban' does not exist on type 'Card'.
Greșeli frecvente
- Folosești
inpe o valoare care poate fi primitivă ("x" in "text"). La rulare aruncă TypeError; tsc te obligă să verifici întâi că este obiect. - Te bazezi pe
inpentru proprietăți opționale: unCardcuiban?ar trece și el testul.
Comenzi înrudite
type guards: Verificări la rulare pe care TypeScript le înțelege și după care știe tipul exact al unei valori.discriminated unions: Un union de obiecte cu o proprietate comună de tip literal; verificarea ei arată exact ce variantă ai.instanceof guard: x instanceof Clasa verifică dacă obiectul a fost creat din clasă și restrânge tipul la acea clasă.narrowing: TypeScript urmărește verificările din cod (if, switch, return) și restrânge tipul unei variabile în fiecare ramură.