Lecții din modul (1/2)
Garzi de tip
Îngustarea tipului este unul dintre cele mai importante concepte din TypeScript. Adesea, totuși, apărările de tip standard precum typeof sau instanceof nu sunt suficiente pentru obiecte personalizate complexe. Aici intervin Custom Type Guards.
Gărzi de tip standard
Să începem prin a rezuma modul în care TypeScript restrânge tipurile folosind operatori JavaScript standard:
function processInput(val: string | number) {
if (typeof val === 'string') {
// Here 'val' is of type string
console.log(val.toUpperCase());
} else {
// Here 'val' is of type number
console.log(val.toFixed(2));
}
}Gărzi de tip personalizat (operator is)
Pentru a defini o gardă de tip personalizat, creăm o funcție care returnează un predicat de tip în formatul parameterName is Type în loc de un tip de returnare boolean standard.
Funcția trebuie să returneze un valor boolean (true sau false). Dacă returnează true, TypeScript va ști că parametrul transmis este de tipul specificat.
interface Cat {
name: string;
meow(): void;
}
interface Dog {
name: string;
bark(): void;
}
// This is a custom type guard
function isCat(animal: Cat | Dog): animal is Cat {
return (animal as Cat).meow !== undefined;
}
function makeNoise(pet: Cat | Dog) {
if (isCat(pet)) {
// Here TypeScript knows 'pet' is a Cat
pet.meow();
} else {
// Here TypeScript knows 'pet' is a Dog
pet.bark();
}
}Siguranță și turnare (as vs Tip Guards)
Casting tip (de exemplu, val as Cat) forțează compilatorul să aibă încredere în dezvoltator fără nicio verificare reală a timpului de rulare. Dacă obiectul runtime nu corespunde așteptărilor, codul va eșua în tăcere sau va arunca excepții.
Protecțiile de tip personalizat, pe de altă parte, efectuează o verificare robustă și dinamică a timpului de execuție, informând în siguranță și cu acuratețe compilatorul TypeScript despre tipul real de variabilă:
function processInput(input: unknown) {
// unsafe casting: could crash if input does not have the split method
// const str = input as string;
// console.log(str.split(' '));
// safe guard
if (isString(input)) {
console.log(input.split(' ')); // 100% Safe!
}
}Încercați-l singur
Exercițiul 1: Garda de tip șir
Creați o funcție simplă numită isString care acționează ca un tip personalizat de gardă pentru a verifica dacă o valoare necunoscută este un șir.
Afișează indiciu
Tipul de returnare al funcției trebuie să fie val is string și ar trebui să utilizați typeof pentru a verifica dacă este egal cu „șir”.
Soluție disponibilă după 3 încercări
Exercițiul 2: Gardă tip utilizator premium
Având în vedere tipurile de Utilizator și Utilizator Premium, scrieți o funcție de pază tip isPremiumUser(utilizator: Utilizator): utilizatorul este PremiumUser care verifică dacă utilizatorul are rolul „premium”.
Afișează indiciu
Definiți semnătura ca funcție isPremiumUser(utilizator: Utilizator): utilizatorul este PremiumUser și comparați user.role cu „premium”.
Soluție disponibilă după 3 încercări
Exercițiul 3: Validarea obiectelor de eroare personalizate
Implementați isCustomError(err: unknown): err este funcția CustomError care verifică dacă o valoare necunoscută este un obiect CustomError non-null care conține cheia „cod”.
Afișează indiciu
Mai întâi verificați dacă typeof err este „obiect” și nu nul, apoi utilizați operatorul „in” pentru a verifica proprietatea „cod”.
Soluție disponibilă după 3 încercări
Exercițiul 4: Garda de tip admin
Având în vedere două interfețe User (cu rol de proprietate: șir) și Admin (extindere User și având o proprietate adminToken: șir), scrieți o funcție de gardă de tip numită isAdmin care acceptă un utilizator de tip User și returnează un tip de utilizator predicat este Admin. Paznicul trebuie să verifice dacă rolul utilizatorului este egal cu „admin”.
Afișează indiciu
Definiți semnătura ca funcție isAdmin(user: User): utilizatorul este Admin și verificați dacă user.role === „admin”.
Soluție disponibilă după 3 încercări