Controllo di esaustività con never
Rilevi i casi non gestiti in fase di compilazione con never.
Controllo di esaustività con never è una lezione TypeScript Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento TypeScript Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso TypeScript Academy include 4 lezioni in totale.
Il problema dell'esaustività
Quando aggiunge un nuovo membro a un'unione, è facile dimenticare di gestirlo in qualche punto. Il controllo di esaustività trasforma questa omissione in un errore di compilazione.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
// If we add "triangle" later, we want every switch to complain.Il tipo never
Il tipo never rappresenta valori che non possono mai verificarsi. Se ogni caso è stato gestito, il valore che raggiunge il ramo predefinito ha tipo never.
function fail(): never {
throw new Error("unreachable");
}
// never is assignable to nothing except never itself.Assegnare a never nel caso predefinito
Nel ramo default, assegni il valore a una variabile di tipo never. Se tutte le varianti sono state gestite, l'assegnazione viene compilata; in caso contrario, genera un errore.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.radius ** 2;
case "square": return s.side ** 2;
default:
const _exhaustive: never = s;
return _exhaustive;
}
}
console.log(area({ kind: "square", side: 3 }));Cosa succede quando si dimentica un caso
Se aggiunge un membro triangle ma dimentica il relativo case, s nel default non è più never, quindi l'assegnazione non viene compilata.
// type Shape = ... | { kind: "triangle"; base: number; height: number };
// Now in default, s is { kind: "triangle"; ... }
// const _exhaustive: never = s; // Error: triangle not assignable to neverL'helper assertNever
Una funzione assertNever riutilizzabile centralizza questo schema. Accetta never e genera un'eccezione, documentando che il ramo non dovrebbe essere raggiungibile.
function assertNever(value: never): never {
throw new Error("Unhandled case: " + JSON.stringify(value));
}
console.log(typeof assertNever);Usare assertNever in uno switch
Chiami assertNever(s) nel caso default. Impone l'esaustività in fase di compilazione e fornisce un errore chiaro a runtime se il ramo viene raggiunto.
function assertNever(value: never): never {
throw new Error("Unhandled: " + JSON.stringify(value));
}
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.radius ** 2;
case "square": return s.side ** 2;
default: return assertNever(s);
}
}
console.log(area({ kind: "circle", radius: 1 }).toFixed(2));Sicurezza in fase di compilazione e a runtime
Il controllo con never rileva i casi mancanti prima dell'esecuzione del codice, mentre l'errore generato protegge il programma se qualcosa supera i controlli dei tipi a runtime.
function assertNever(x: never): never {
throw new Error("Unhandled: " + String(x));
}
// Compile error if a case is missing; runtime throw as a backstop.
console.log("two layers of safety");Esaustività senza default
Se la funzione ha un tipo di ritorno esplicito e uno switch copre ogni caso, TypeScript può anche segnalare un return mancante: un'altra forma di controllo dell'esaustività.
type Light = "red" | "yellow" | "green";
function next(l: Light): Light {
switch (l) {
case "red": return "green";
case "yellow": return "red";
case "green": return "yellow";
}
// No default needed; all cases return.
}
console.log(next("red"));Esaustività con catene if/else
La stessa idea funziona con if/else. Dopo aver gestito ogni variante, l'ultimo else riceve un valore never.
function assertNever(x: never): never { throw new Error("bad"); }
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function name(s: Shape): string {
if (s.kind === "circle") return "circle";
else if (s.kind === "square") return "square";
else return assertNever(s);
}
console.log(name({ kind: "square", side: 2 }));Perché never è lo strumento giusto
Poiché never non è assegnabile ad alcun tipo, ogni variante rimasta fa fallire l'assegnazione. Questo rende never il rilevatore perfetto dei casi non gestiti.
// Only never is assignable to never.
let x: never;
// x = "hi"; // Error
// Any concrete leftover type fails the same way.
console.log("never catches gaps");L'esaustività come rete di sicurezza per il refactoring
Con assertNever in ogni punto necessario, l'aggiunta di un membro all'unione produce un elenco ordinato di errori di compilazione che indica esattamente ogni punto da aggiornare.
function assertNever(x: never): never { throw new Error("unhandled"); }
type Status = "idle" | "busy";
function render(s: Status): string {
switch (s) {
case "idle": return "Idle";
case "busy": return "Busy";
default: return assertNever(s);
}
}
console.log(render("idle"));Verifica rapida: esaustività
Verifichi la sua comprensione del controllo di esaustività.
Riepilogo: esaustività con never
Ha imparato ad assegnare il valore predefinito a never (oppure a passarlo a assertNever) affinché il compilatore imponga la gestione di ogni variante. In questo modo, i casi dimenticati diventano errori di compilazione.
function assertNever(x: never): never { throw new Error("unhandled"); }
type Shape = { kind: "circle"; radius: number } | { kind: "square"; side: number };
function f(s: Shape) {
switch (s.kind) {
case "circle": return s.radius;
case "square": return s.side;
default: return assertNever(s);
}
}
console.log(f({ kind: "circle", radius: 5 }));Domande Frequenti
La lezione «Controllo di esaustività con never» è gratuita?
Sì — il testo completo di «Controllo di esaustività con never» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso TypeScript Academy, passa a CoddyKit PRO. Il corso TypeScript Academy include 4 lezioni in totale.
Cosa imparerò in «Controllo di esaustività con never»?
Rilevi i casi non gestiti in fase di compilazione con never. Eserciti TypeScript Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare TypeScript Academy?
Non è richiesta alcuna esperienza precedente. TypeScript Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Controllo di esaustività con never»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione TypeScript Academy?
Sì. Ogni lezione TypeScript Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Costruire union discriminate
- Restringimento tramite discriminante
- Controllo di esaustività con never
- Modellare macchine a stati