I have some code:
enum Color {
Red,
Green,
Blue
}
function getColorName(c: Color): string {
switch(c) {
case Color.Red:
return 'red';
case Color.Green:
return 'green';
// Forgot about Blue
}
throw new Error('Did not expect to be here');
}
I forgot to handle the Color.Blue
case and I'd prefer to have gotten a compile error. How can I structure my code such that TypeScript flags this as an error?
You don't need to use
never
or add anything to the end of yourswitch
.If
switch
statement returns in each casestrictNullChecks
typescript compilation flag turned onundefined
orvoid
You will get an error if your
switch
statement is non-exhaustive as there will be a case where nothing is returned.From your example, if you do
You will get the following compilation error:
What I do is to define an error class:
and then throw this error in the default case:
I think it's easier to read because the
throw
clause has the default syntax highlighting.Building on top of Ryan's answer, I discovered here that there is no need for any extra function. We can do directly:
You can see it in action here in TS Playground
To do this, we'll use the
never
type (introduced in TypeScript 2.0) which represents values which "shouldn't" occur.First step is to write a function:
Then use it in the
default
case (or equivalently, outside the switch):At this point, you'll see an error:
The error message indicates the cases you forgot to include in your exhaustive switch! If you left off multiple values, you'd see an error about e.g.
Color.Blue | Color.Yellow
.Note that if you're using
strictNullChecks
, you'll need thatreturn
in front of theassertUnreachable
call (otherwise it's optional).You can get a little fancier if you like. If you're using a discriminated union, for example, it can be useful to recover the discriminant property in the assertion function for debugging purposes. It looks like this:
This is a nice pattern because you get compile-time safety for making sure you handled all the cases you expected to. And if you do get a truly out-of-scope property (e.g. some JS caller made up a new
species
), you can throw a useful error message.Create a custom function instead of using a
switch
statement.Example usage
If you later add
d
toMyEnum
, you will receive an errorProperty 'd' is missing in type ...
In really simple cases when you just need to return some string by enum value it's easier (IMHO) to use some constant to store dictionary of results instead of using switch. For example:
So here you will have to mention every enum value in constant, otherwise you get an error like, for example, if Blue is missing:
However it's often not the case and then it's really better to throw an error just like Ryan Cavanaugh proposed.
Also I was a bit upset when found that this won't work also: