Ce face exactOptionalPropertyTypes
Pentru TypeScript, telefon?: string înseamnă implicit „string sau undefined, sau lipsește”. În JavaScript, o proprietate care lipsește nu este însă același lucru cu una care există și are valoarea undefined: "telefon" in obj, Object.keys și operatorul spread le tratează diferit.
Cu exactOptionalPropertyTypes, telefon?: string înseamnă doar „lipsește sau este string”. Ca să permiți și undefined scris explicit, declari email?: string | undefined.
Implicit este false și nu face parte din strict. Are nevoie de strictNullChecks. tsc --init din 5.9 o pornește în fișierul nou, la „Stricter Typechecking Options”.
Parametri
| Parametru | Descriere |
|---|---|
true |
Proprietățile opționale nu acceptă undefined decât dacă îl scrii în tip. |
false |
Valoarea implicită. p?: T acceptă și undefined. |
Exemple
Exemplul 1: undefined pus explicit
telefon: undefined nu este permis, pentru că tipul spune doar string. Pentru email, tipul include undefined, deci b este corect.
// tsconfig.json
{
"compilerOptions": {
"strict": true,
"exactOptionalPropertyTypes": true
}
}
// index.ts
interface Client {
nume: string;
telefon?: string;
email?: string | undefined;
}
const a: Client = { nume: "Ana", telefon: undefined };
const b: Client = { nume: "Ion", email: undefined };
console.log(a, b);
Rezultat (tsc 5.9)
$ npx tsc --noEmit
index.ts(7,7): error TS2375: Type '{ nume: string; telefon: undefined; }' is not assignable to type 'Client' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
Types of property 'telefon' are incompatible.
Type 'undefined' is not assignable to type 'string'.
Exemplul 2: De ce contează diferența
Cele două obiecte arată la fel când citești telefon, dar nu sunt la fel pentru in, Object.keys și spread: în al doilea, valoarea undefined suprascrie telefonul vechi.
interface Client {
nume: string;
telefon?: string | undefined;
}
const lipsa: Client = { nume: "Ana" };
const gol: Client = { nume: "Ana", telefon: undefined };
console.log(lipsa.telefon, gol.telefon);
console.log("telefon" in lipsa, "telefon" in gol);
console.log(Object.keys(lipsa), Object.keys(gol));
const vechi = { nume: "Ana", telefon: "0722 000 111" };
console.log({ ...vechi, ...lipsa }.telefon);
console.log({ ...vechi, ...gol }.telefon);
Rezultat
undefined undefined
false true
[ 'nume' ] [ 'nume', 'telefon' ]
0722 000 111
undefined
Greșeli frecvente
- Să pornești opțiunea într-un proiect mare fără să te aștepți la multe erori: codul de forma
{ x: valoare ?? undefined }este foarte des întâlnit. - Să crezi că opțiunea schimbă ceva la rulare. Doar verificarea tipurilor se schimbă.
Comenzi înrudite
strictNullChecks: Face din null și undefined tipuri separate: o valoare care poate lipsi trebuie verificată înainte de folosire.noUncheckedIndexedAccess: Adaugă undefined la tipul valorilor citite cu index (note[0], stoc[„pere”]), pentru că ele pot lipsi.--init: Creează un fișier tsconfig.json nou, cu setările recomandate de versiunea curentă de TypeScript.