ProgrammazioneSviluppatore Frontend

Descrivi il meccanismo delle type guards in TypeScript e fornisci esempi del loro uso. Qual è il principale vantaggio e quali aspetti bisogna considerare nella realizzazione delle funzioni di type guard personalizzate?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

Le type guards sono meccanismi che permettono di affinare il tipo di una variabile in un blocco di codice, basandosi su alcune verifiche (ad esempio, utilizzando typeof, instanceof, oppure funzioni speciali che restituiscono espressioni del tipo param is SomeType).

Il principale vantaggio è la sicurezza e l'esclusione di errori di esecuzione grazie alla verifica dei tipi durante la compilazione.

Esempio:

interface Fish { swim: () => void } interface Bird { fly: () => void } function isFish(pet: Fish | Bird): pet is Fish { return (pet as Fish).swim !== undefined; } function move(pet: Fish | Bird) { if (isFish(pet)) { pet.swim(); } else { pet.fly(); } }

Qui la funzione isFish è una type guard personalizzata.

Aspetti da considerare:

  • Qualsiasi verifica logica aggiuntiva deve essere strettamente legata alla tipizzazione.
  • Errori nelle funzioni di type guard possono portare a una definizione errata dei tipi durante l'esecuzione.

Domanda insidiosa.

Domanda: "Il compilatore TypeScript si basa sempre solo sul valore restituito dalla funzione guard, o utilizza anche un'analisi interna alla funzione?"

Risposta: Il compilatore TypeScript si basa solo sulla firma del valore restituito param is Type. Ciò che accade all'interno della funzione guard non viene analizzato per la correttezza dell'implementazione.

Esempio (errore pericoloso!):

function isString(x: any): x is string { return true; } // Il compilatore considererà sempre che sia una stringa, anche se non lo è: if (isString(123)) { // qui x è di tipo string, ma in realtà è un numero }

Esempi di errori reali dovuti all'ignoranza delle sottigliezze dell'argomento.


Storia

In un progetto con DTO condivisi tra frontend e backend, è stata dimenticata l'aggiunta di una verifica rigorosa all'interno della type guard personalizzata. Di conseguenza, parte dei dati venivano erroneamente interpretati come un tipo necessario, causando malfunzionamenti sul client quando si cercava di utilizzare una proprietà mancante.


Storia

Un programmatore ha scritto una type guard, confidando su un campo opzionale, tuttavia la struttura dei dati permetteva di non avere affatto quel campo. Alla fine, al costrutto switch-case tipizzato mancava un ramo, e il compilatore non ha mostrato avvisi — si sono verificati eccezioni in fase di runtime.


Storia

In uno dei servizi, durante il passaggio a TypeScript, ci si è affidati solo alle type guards integrate (typeof, instanceof). Quando il prototipo degli oggetti cambiatava durante l'esecuzione, le verifiche diventavano errate, causando bug difficili da debugare in produzione.