W tym celu użyjemy typu never
(wprowadzonego w TypeScript 2.0), który reprezentuje wartości, które "nie powinny" występować.
Pierwszym krokiem jest napisanie funkcji:
function assertUnreachable(x: never): never {
throw new Error("Didn't expect to get here");
}
następnie użyć go w przypadku default
(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 zapomniane umieścić w swoim wyczerpujący przełącz! Jeśli przerwiesz 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 return
przed wywołaniem assertUnreachable
(w przeciwnym razie jest to opcjonalne).
Możesz dostać trochę hodowcy, jeśli chcesz. Jeśli na przykład korzystasz z dyskryminowanej unii, może być przydatne odzyskanie właściwości dyskryminacyjnej w funkcji asercji w celu debugowania. Wygląda to tak:
// Discriminated union using string literals
interface Dog {
species: "canine";
woof: string;
}
interface Cat {
species: "feline";
meow: string;
}
interface Fish {
species: "pisces";
meow: string;
}
type Pet = Dog | Cat | Fish;
// Externally-visible signature
function throwBadPet(p: never): never;
// Implementation signature
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:
// Argument of type 'Fish' not assignable to 'never'
throwBadPet(p);
}
}
To jest ładny wzór, ponieważ zapewniasz bezpieczeństwo podczas kompilacji, aby upewnić się, że załatwiłeś wszystkie sprawy, których się spodziewałeś. A jeśli dostaniesz naprawdę zewnętrzną właściwość (np. Jakiś wywołujący JS wymyślił nowy species
), możesz rzucić przydatny komunikat o błędzie.
Przy włączonej opcji "strictNullChecks', nie wystarczy zdefiniować typ zwracany przez funkcję jako' string', bez konieczności używania funkcji 'assertUnreachable'? – dbandstra
@dbandstra Z pewnością możesz to zrobić, ale jako ogólny wzór assertUnreachable jest bardziej niezawodny. Działa nawet bez 'strictNullChecks', a także kontynuuje pracę, jeśli istnieją warunki, w których chcesz wrócić niezdefiniowany z zewnątrz przełącznika. – Letharion