Aby to zrobić, użyjemy nevertypu (wprowadzonego w TypeScript 2.0), który reprezentuje wartości, które „nie powinny” wystąpić.
Pierwszym krokiem jest napisanie funkcji:
function assertUnreachable(x: never): never {
throw new Error("Didn't expect to get here");
}
Następnie użyj go w defaultobudowie (lub równoważnie poza przełącznikiem):
function getColorName(c: Color): string {
switch(c) {
case Color.Red:
return 'red';
case Color.Green:
return 'green';
}
return assertUnreachable(c);
}
W tym momencie zobaczysz błąd:
return assertUnreachable(c);
~~~~~~~~~~~~~~~~~~~~~
Type "Color.Blue" is not assignable to type "never"
Komunikat o błędzie wskazuje przypadki, które zapomniałeś uwzględnić w swoim wyczerpującym przełączniku! Jeśli pominiesz wiele wartości, zobaczysz błąd dotyczący np Color.Blue | Color.Yellow.
Pamiętaj, że jeśli używasz strictNullChecks, będziesz potrzebować tego returnprzed assertUnreachablepołączeniem (w przeciwnym razie jest to opcjonalne).
Jeśli chcesz, możesz stać się trochę bardziej wyszukany. Jeśli na przykład używasz unii rozłącznej, przydatne może być odzyskanie właściwości dyskryminacyjnej w funkcji potwierdzenia na potrzeby debugowania. To wygląda tak:
interface Dog {
species: "canine";
woof: string;
}
interface Cat {
species: "feline";
meow: string;
}
interface Fish {
species: "pisces";
meow: string;
}
type Pet = Dog | Cat | Fish;
function throwBadPet(p: never): never;
function throwBadPet(p: Pet) {
throw new Error('Unknown pet kind: ' + p.species);
}
function meetPet(p: Pet) {
switch(p.species) {
case "canine":
console.log("Who's a good boy? " + p.woof);
break;
case "feline":
console.log("Pretty kitty: " + p.meow);
break;
default:
throwBadPet(p);
}
}
To fajny wzorzec, ponieważ zyskujesz bezpieczeństwo w czasie kompilacji, aby upewnić się, że obsłużyłeś wszystkie przypadki, których się spodziewałeś. A jeśli rzeczywiście otrzymasz właściwość poza zakresem (np. Jakiś obiekt wywołujący JS wymyślił nowy species), możesz wyrzucić użyteczny komunikat o błędzie.