In TypeScript, il pattern matching è implementato tramite gli "union discriminati". A ciascun oggetto nell'unione viene assegnato un campo discriminatore obbligatorio (di solito una stringa, ad esempio type), in base al quale TypeScript differenzia le varianti.
Esempio:
type Success = { type: 'success'; data: string }; type Failure = { type: 'failure'; error: string }; type Result = Success | Failure; function handleResult(result: Result) { switch (result.type) { case 'success': // result: Success console.log(result.data); break; case 'failure': // result: Failure console.error(result.error); break; } }
In switch/case o if sul campo discriminatore, TypeScript "restringerà" il tipo esattamente alla variante desiderata.
Principali vantaggi:
Se aggiungi una nuova variante nell'unione discriminata, TypeScript richiederà forzatamente di aggiornare tutti i switch-case per gestire la nuova variante?
Risposta: No, solo se si aggiunge esplicitamente la gestione della variante "impossibile". Ad esempio, utilizzare la funzione never:
Esempio:
function assertNever(x: never): never { throw new Error('Variant imprevista: ' + x); } function handle(r: Result) { switch(r.type) { case 'success': /* ... */; break; case 'failure': /* ... */; break; default: return assertNever(r); // TS genererà un errore se appare un nuovo tipo } }
Storia
Dopo aver ampliato il tipo "Result" con una nuova variante ('pending'), in diversi punti dell'applicazione i vecchi switch-case non gestivano questo caso. Di conseguenza, alcune interfacce hanno smesso di funzionare. L'errore è stato notato solo in produzione una settimana dopo il rilascio.
Storia
Il tentativo di utilizzare un'unione discriminata senza un discriminatore unico (il campo type duplicato in due tipi) ha portato a una "sfocatura" dei tipi: TypeScript ha smesso di restringere il tipo con precisione, ed è diventato possibile accedere a campi inesistenti senza errore di compilazione. Diversi bug critici sono stati inviati in produzione.
Storia
Nel progetto, il pattern matching è stato implementato tramite if-else su più campi invece di utilizzare un unico discriminatore esplicito. Questo ha complicato il passaggio alla verifica di exhaustiveness con la funzione never ed ha reso la leggibilità del codice più difficile — gli switch-case non funzionavano correttamente e le nuove varianti "rompevano" la logica esistente.