Passer au contenu principal
eLearner.app
Module 5 · Leçon 1 sur 29/14 dans le cours~15 min
Leçons du module (1/2)

Guardie di Tipo

Il restringimento dei tipi (Type Narrowing) è uno dei concetti più importanti in TypeScript. Spesso, però, le guardie di tipo standard come typeof o instanceof non sono sufficienti per oggetti personalizzati complessi. È qui che entrano in gioco le Guardie di Tipo Personalizzate (Custom Type Guards).

Guardie di Tipo Standard

Iniziamo riepilogando come TypeScript restringe i tipi usando gli operatori standard di JavaScript:

TS
function processInput(val: string | number) {
  if (typeof val === 'string') {
    // Qui 'val' è di tipo string
    console.log(val.toUpperCase());
  } else {
    // Qui 'val' è di tipo number
    console.log(val.toFixed(2));
  }
}

Guardie di Tipo Personalizzate (is operator)

Per definire una guardia di tipo personalizzata, creiamo una funzione che restituisce un predicato di tipo nel formato parameterName is Type al posto del tipo di ritorno booleano standard.

La funzione deve restituire un booleano (true o false). Se restituisce true, TypeScript saprà che il parametro passato è del tipo specificato.

TS
interface Cat {
  name: string;
  meow(): void;
}

interface Dog {
  name: string;
  bark(): void;
}

// Questa è una guardia di tipo personalizzata
function isCat(animal: Cat | Dog): animal is Cat {
  return (animal as Cat).meow !== undefined;
}

function makeNoise(pet: Cat | Dog) {
  if (isCat(pet)) {
    // Qui TypeScript sa che 'pet' è un Cat
    pet.meow();
  } else {
    // Qui TypeScript sa che 'pet' è un Dog
    pet.bark();
  }
}

Sicurezza e Casting (as vs Type Guards)

Il type casting (es. val as Cat) forza il compilatore a fidarsi dello sviluppatore, senza alcuna verifica reale a runtime. Se l'oggetto a runtime non rispetta le aspettative, il codice fallirà silenziosamente o lancerà eccezioni.

Le guardie di tipo personalizzate permettono invece di eseguire un controllo robusto e dinamico a runtime, informando in modo sicuro e preciso il compilatore di TypeScript sul reale tipo della variabile:

TS
function processInput(input: unknown) {
  // casting insicuro: potrebbe rompersi se input non ha il metodo split
  // const str = input as string;
  // console.log(str.split(' '));

  // guardia sicura
  if (isString(input)) {
    console.log(input.split(' ')); // Sicuro al 100%!
  }
}

Prova tu

Esercizio 1: Guardia di Tipo per Stringhe

Exercice#ts.m5.l1.e1
Tentatives : 0Chargement…

Crea una semplice funzione chiamata isString che funziona come guardia di tipo personalizzata per verificare se un valore unknown è una stringa.

Chargement de l'éditeur…
Afficher l'indice

Il tipo di ritorno della funzione deve essere val is string, e devi usare typeof per verificare se è uguale a 'string'.

Solution disponible après 3 tentatives

Esercizio 2: Guardia di Tipo per Utente Premium

Exercice#ts.m5.l1.e2
Tentatives : 0Chargement…

Dati i tipi User e PremiumUser, scrivi una funzione guardia di tipo isPremiumUser(user: User): user is PremiumUser che controlla se l'utente ha il ruolo 'premium'.

Chargement de l'éditeur…
Afficher l'indice

Definisci la firma come function isPremiumUser(user: User): user is PremiumUser e confronta user.role con 'premium'.

Solution disponible après 3 tentatives

Esercizio 3: Verifica Oggetto Errore Personalizzato

Exercice#ts.m5.l1.e3
Tentatives : 0Chargement…

Implementa la funzione isCustomError(err: unknown): err is CustomError che verifica se un valore sconosciuto è un oggetto CustomError non nullo che possiede la chiave 'code'.

Chargement de l'éditeur…
Afficher l'indice

Verifica prima che typeof err sia 'object' e non sia null, quindi usa l'operatore 'in' per verificare la presenza della proprietà 'code'.

Solution disponible après 3 tentatives

Esercizio 4: Guardia di Tipo Admin

Exercice#ts.m5.l1.e4
Tentatives : 0Chargement…

Date due interfacce User (con proprietà role: string) e Admin (che estende User e ha una proprietà adminToken: string), scrivi una funzione type guard chiamata isAdmin che accetta un oggetto user di tipo User e restituisce un predicato di tipo user is Admin. La guardia deve verificare che il role dell'utente sia uguale a 'admin'.

Chargement de l'éditeur…
Afficher l'indice

Definisci la firma come function isAdmin(user: User): user is Admin e controlla che user.role === 'admin'.

Solution disponible après 3 tentatives