Saltar al contenido principal
eLearner.app
Módulo 5 · Lección 1 de 29/14 en el curso~15 min
Lecciones del módulo (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

Ejercicio#ts.m5.l1.e1
Intentos: 0Cargando...

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

Cargando editor...
Mostrar pista

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

Solución disponible después de 3 intentos

Esercizio 2: Guardia di Tipo per Utente Premium

Ejercicio#ts.m5.l1.e2
Intentos: 0Cargando...

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'.

Cargando editor...
Mostrar pista

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

Solución disponible después de 3 intentos

Esercizio 3: Verifica Oggetto Errore Personalizzato

Ejercicio#ts.m5.l1.e3
Intentos: 0Cargando...

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'.

Cargando editor...
Mostrar pista

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

Solución disponible después de 3 intentos

Esercizio 4: Guardia di Tipo Admin

Ejercicio#ts.m5.l1.e4
Intentos: 0Cargando...

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'.

Cargando editor...
Mostrar pista

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

Solución disponible después de 3 intentos