-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
[switch-exhaustiveness-check] ban the default case to enforce all cases are handled and prevent accidental mishandling of new cases #3616
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Existing rule that is somewhat related to this request - For When paired with However For example type MyUnion = 'a' | 'b' | 'c';
declare const myUnion: MyUnion;
if (myUnion === 'a' || myUnion === 'b') {
// ...
} else {
// ...
}
if (myUnion !== 'b' && myUnion !== 'c') {
// ...
} else {
// ...
}
if (myUnion === 'a' && otherCondition === 'someValue') {
// ...
} else if ((myUnion === 'b' || myUnion === 'c') && otherCondition === 'other') {
// ...
} |
TS seems to understand the control flow and narrow the type, so I was hoping we could benefit from this information in a lint rule—rather than trying to infer it for ourselves. type MyUnion = 'a' | 'b' | 'c';
declare const myUnion: MyUnion;
if (myUnion === 'a' || myUnion === 'b') {
// ...
} else {
myUnion; // TS knows this is `'c'`
}
if (myUnion !== 'b' && myUnion !== 'c') {
// ...
} else {
myUnion; // TS knows this is `'b' | 'c'`
}
declare const otherCondition: 'someValue' | 'other' | 'foo'
if (myUnion === 'a' && otherCondition === 'someValue') {
// ...
} else if ((myUnion === 'b' || myUnion === 'c') && otherCondition === 'other') {
myUnion; // TS knows this is `'b' | 'c'`
} Is that possible? |
Ah I think I see what you're saying now, my bad! |
yeah the problem isn't know what type the thing is - we can definitely do that whenever we've got the identifier in the code. The problems are: (1) an (2) I don't believe that there's an easy way for us to speculatively ask TS things at certain points in the code. Eg "hey TS, we have an (3) Because ifs are so flexible, it's really hard to understand developer intent or provide strong lint guidance. For example: declare const myUnion: 'a' | 'b' | 'c';
if (myUnion === 'a') {
// ..
} else {
// ..
} Is this a bad The logic and number of cases sort of explodes every quickly for But switch/cases are very simple in structure and are thus easy to deal with :) |
That makes sense, thanks for explaining. I guess for switches it could be as simple as banning |
I'd be happy to see an option in |
Similarly, I'd like an option to simultaneously allow
|
It doesn't appear so. The difference is that I am looking for exhaustive AND an optional |
So to summarize. Here are the things being proposed here. For a non-exhaustive
*Note: switches against infinite types are always non-exhaustive by definition.
Is this correct? |
|
@JoshuaKGoldberg there is still a bug here: '@typescript-eslint/switch-exhaustiveness-check': [
'error',
{
allowDefaultCaseForExhaustiveSwitch: false,
requireDefaultForNonUnion: true
}
], const getRandomString = (): string => 'asdf';
const x = getRandomString();
switch (x) {
case 'aszdfasdf':
break;
default:
^^^^^^^
break;
^^^^^
}
The switch statement is not exhaustive. |
This needs to reopen |
Duplicate of #8165. This issue is for implementing a feature; bugs related to the feature are separate issues. |
I frequently see code like this:
The logic in
f1
makes an assumption: ifmyUnion
is nota
, it must beb
.Later on, someone might update the
MyUnion
type and this assumption will breakdown:The runtime behaviour is clearly incorrect, yet TypeScript will not error to remind us that we need to update the logic in
f1
:This problem is not specific to the ternary operator but also
if
andswitch
statements:As we can see, it is not safe to make assumptions about the value that reaches the
else
/default
case because it can change.Instead we need to explicitly specify all cases:
This way, when the type is eventually widened, TypeScript will generate a type error so we're reminded that we need to update our code:
I would like to propose a rule that enforces this. The rule would report an error inside a ternary or
if
/switch
statement if we're switching over a union type (exceptboolean
) and we have a fallback case (else
/default
). The fix would be to explicitly specify all cases.I'm really not sure what we would call it.
WDYT?
The text was updated successfully, but these errors were encountered: