I want to do a kind of opposite exhaustive check as the one mentioned here:
How do I check that a switch block is exhaustive in TypeScript?
ie. something like this:
enum Color {
Red = "Red",
Green = "Green",
Blue = "Blue"
}
function convertStringToColor(str: string ): Color {
switch(str) {
case Color.Red:
case Color.Green:
return str;
default: {
assertNotStillColor(str); // ???
throw new Error("String did not match any of the known enum values");
}
}
}
That is, if we've forgotten to check all of our enum types, we should see a type error. But the default code block can still be enountered, without a type error, in the scenario that a non-matching string is encountered.
The typical exhaustiveness check does not work in this scenario - the type of str is still string.
I've tried something like this:
function assertNotStillColor(str: Exclude){
}
This theoretically could work, but TypeScript as I understand it, doesn't have a concept of 'any string except these ones'.
This does work:
type KnownStrings = "Foo" | Color;
function assertNotStillColor(str: Exclude){
}
function convertStringToColor(str: KnownStrings ): Color {
switch(str) {
case Color.Red:
case Color.Green:
case Color.Blue:
return str;
default: {
assertNotStillColor(str);
throw new Error("String did not match any of the known enum values");
}
}
}
But this isn't really what we want - we want this function to accept any string.
I suppose I can do this:
function convertStringToColor(str: string ): Color {
const str2 = str as Color;
switch(str2) {
case Color.Red:
case Color.Blue:
case Color.Green:
return str2;
default: {
assertNotStillColor(str2);
throw new Error("String did not match any of the known enum values");
}
}
}
It works.
Anything better?