Treci la conținutul principal

Gărzi de tip în TypeScript

O gardă de tip este o verificare care restrânge tipul unei variabile în interiorul unui bloc de cod. După verificare, TypeScript cunoaște tipul mai precis și îți permite să îl folosești în siguranță.


Cum funcționează gărzile de tip în TypeScript

Gărzile de tip sunt verificări explicite care stabilesc tipul exact al unei valori în timpul execuției. TypeScript citește aceste verificări și restrânge tipul în codul care urmează.

De ce să folosești gărzi de tip?

  • Siguranța tipurilor: operațiile se execută doar pe valori de tipul potrivit
  • Claritatea codului: verificarea tipului este explicită și se documentează singură
  • Unelte mai bune: editorul oferă completare corectă pentru tipul restrâns
  • Prevenirea erorilor: greșelile de tip sunt prinse la compilare
  • Siguranță la execuție: verificarea protejează codul și în timp ce rulează

Tipare de gărzi de tip prezentate pe această pagină:

  • gărzi de tip cu typeof
  • gărzi de tip cu instanceof
  • gărzi de tip definite de utilizator, cu predicate de tip
  • reuniuni discriminate cu tipuri literale
  • gărzi de tip cu operatorul in
  • funcții de aserțiune de tip

Gărzi de tip cu typeof

Operatorul typeof este o gardă de tip inclusă în limbaj. El verifică tipul unei valori primitive în timpul execuției.

Este cel mai util pentru restrângerea reuniunilor de primitive precum string, number și boolean.

Utilizare de bază

În interiorul ramurii if (typeof value === 'string'), TypeScript tratează value ca string. În ramura else este un number. Fiecare ramură poate apela metodele tipului său.

Prompt
Arată o gardă de tip cu typeof care restrânge un parametru string | number. Scrie o funcție formatValue(value: string | number): string care, pe ramura de string, elimină spațiile și transformă valoarea în majuscule, iar pe ramura de number apelează toFixed(2), apoi apeleaz-o cu ' salut ' și 42.1234, păstrând rezultatele în result1 și result2, cu comentarii care arată "SALUT" și "42.12". Exemplul nu afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Gărzi de tip cu instanceof

Operatorul instanceof verifică dacă un obiect a fost creat de o anumită clasă sau funcție constructor.

Folosește-l pentru a restrânge reuniuni de instanțe de clase sau de obiecte incluse în limbaj.

Restrângerea tipului pe bază de clasă

Verificarea animal instanceof Bird restrânge animal la Bird în prima ramură, așa că fly() este permis. În ramura else valoarea trebuie să fie un Fish.

Prompt
Arată o gardă de tip cu instanceof care restrânge o reuniune de două clase. Declară o clasă Bird cu o metodă fly() care afișează Zboară... și o clasă Fish cu o metodă swim() care afișează Înoată..., apoi o funcție move(animal: Bird | Fish) care apelează fly() când animal instanceof Bird și swim() în caz contrar. Exemplul doar definește funcția și nu afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Gărzi de tip definite de utilizator

Pentru verificări mai complexe poți scrie propria funcție gardă de tip. Tipul ei de retur este un predicat de tip, de forma parameterName is Type.

Funcții cu predicat de tip

Semnătura vehicle is Car îi spune lui TypeScript: când această funcție returnează true, tratează vehicle ca pe un Car. În ramura else este restrâns la Motorcycle.

Prompt
Arată o gardă de tip definită de utilizator care returnează un predicat de tip. Declară interfețele Car (make, model, year, plus un type?: undefined opțional, ca să nu poată fi confundată cu o motocicletă) și Motorcycle (aceleași câmpuri plus type: "sport" | "cruiser"), o funcție isCar(vehicle: Car | Motorcycle): vehicle is Car care verifică dacă proprietatea type este undefined, și o funcție displayVehicleInfo care afișează marca, modelul și anul, apoi afișează Acesta este un automobil sau Aceasta este o motocicletă <type>, în funcție de gardă. Doar definiții, fără apeluri, așa că nu se afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Reuniuni discriminate

O reuniune discriminată (numită și reuniune etichetată) este o reuniune de tipuri obiect care au în comun o proprietate, discriminantul. Valoarea lui literală deosebește tipurile între ele.

Acest tipar funcționează foarte bine împreună cu gărzile de tip.

Reuniune discriminată de bază

Proprietatea comună kind este discriminantul. Un switch pe shape.kind restrânge shape la Circle sau Square în fiecare caz.

Prompt
Arată o reuniune discriminată restrânsă cu un switch pe discriminant. Declară interfețele Circle (kind: "circle", radius) și Square (kind: "square", sideLength), o reuniune Shape și o funcție calculateArea(shape: Shape) care face switch pe shape.kind și returnează Math.PI * radius ** 2 pentru cercuri și sideLength ** 2 pentru pătrate. Doar definiții, nu se afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Operatorul in

Operatorul in verifică dacă un obiect are o anumită proprietate.

Este util pentru restrângerea reuniunilor ale căror membri au nume diferite de proprietăți.

Verificarea existenței unei proprietăți

Doar Dog are o proprietate bark, așa că "bark" in animal restrânge animal la Dog. Altfel, trebuie să fie un Cat.

Prompt
Arată operatorul in folosit ca gardă de tip. Declară o interfață Dog cu o metodă bark(): void și o interfață Cat cu meow(): void, apoi o funcție makeSound(animal: Dog | Cat) care apelează bark() când "bark" in animal și meow() în caz contrar. Doar definiții, nu se afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Funcții de aserțiune de tip

O funcție de aserțiune de tip este o gardă de tip specială. În loc să returneze true sau false, ea aruncă o eroare atunci când verificarea eșuează. După apel, TypeScript tratează valoarea ca fiind de tipul asertat.

Sunt utile pentru validarea datelor în timpul execuției.

Funcții de aserțiune

asserts value is string restrânge value la string după apel. asserts condition îi spune lui TypeScript că, din acel punct înainte, condiția este adevărată, așa că value devine un number.

Prompt
Arată funcții de aserțiune de tip care aruncă o eroare la intrare invalidă. Scrie assertIsString(value: unknown): asserts value is string, care aruncă Valoarea nu este un string pentru valori care nu sunt string-uri, și assert(condition: unknown, message: string): asserts condition, care aruncă mesajul primit când condiția este falsă. Apoi scrie processInput(input: unknown), care apelează assertIsString și afișează input.toUpperCase(), și processNumber(value: unknown): number, care asertează typeof value === 'number' și returnează value * 2. Doar definiții, nu se afișează nimic.
Ieșire: program TypeScript și rezultatul capturat

Bune practici

Când folosești fiecare gardă de tip:

  • Folosește typeof pentru tipuri primitive (string, number, boolean și așa mai departe)
  • Folosește instanceof pentru instanțe de clase și obiecte incluse în limbaj
  • Folosește gărzi de tip definite de utilizator pentru logică de validare complexă
  • Folosește reuniuni discriminate pentru tipuri înrudite care au în comun o proprietate discriminant
  • Folosește operatorul in pentru a verifica dacă există o proprietate
  • Folosește funcții de aserțiune de tip pentru validări la execuție care trebuie să arunce o eroare

Considerații de performanță:

  • typeof și instanceof sunt foarte rapide
  • Evită logica grea în interiorul gărzilor de tip definite de utilizator atunci când performanța contează
  • Pune verificările costisitoare care rulează de multe ori într-o funcție cu predicat de tip