TypeScript: Narrowing types by `typeof` inside `switch (true)` does not work
TypeScript Version: 3.8.3 Nightly
Search Terms:
- switch statement
- switch (true)
Code
let x: string | undefined;
if (typeof x !== 'undefined') {
x.trim(); // works as expected
}
switch (true) {
case typeof x !== 'undefined':
x.trim(); // thinks x is potentially undefined
}
Expected behavior:
Narrowing types should work inside the case.
Actual behavior:
Any assertion in case seems to be disregarded
Related Issues:
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 47
- Comments: 20 (6 by maintainers)
Commits related to this issue
- Error: typescript doesn't type infer switch statement https://github.com/microsoft/TypeScript/issues/37178 — committed to letwebdev/hackernews by letwebdev 9 months ago
Two come to mind: • readability for big amounts of cases • being able to use fall-throughs for overlapping cases
Having said that I understand it is an edge case. I came across this pattern in a bigger codebase and wanted to make a change. That’s when I noticed that the types are not narrowed in each case.
I have similar usecase:
And I am using this syntax in javascript because it looks better than chain of if else. Sadly can not use in typescript
I try not to pollute open issues with fluff like “me too!”, but in the related closed thread I was surprised to see this commented as a ‘wontfix’ as it is not a ‘common pattern’. Those comments were in 2016. I find this pattern a very clean and elegant approach that can be reused across an entire codebase to consistently handle very different scenarios.
Anecdotally, I see this pattern more and more in the wild.
@sandersn @RyanCavanaugh Would you still consider this an uncommon pattern today?
Never seen code like that before 😄. If you rewrite the
ifstatement to be roughly equivalent to theswitchstatement, you get the same failure:Which makes this a duplicate of… well, I couldn’t find an existing ticket. But I’m reasonably sure narrowing
=== trueand=== falsepatterns was rejected before because it adds perf costs for an uncommonly used idiom.The third advantage is that in some cases it tastes as poor man’s pattern matching.
Has there been any opdate or in progress work on this?
Fourth adwantage is when having to narrow an input which can be a primitive or a specific object type/class instance:
Not arguing at all that the shape is a bit odd, but if there are many variants for what you’re switching over then it is more readable than a bunch of if/else if.
Best argument I’ve heard for switch(true) is that sometimes you need to execute only one of lots of possible things and it most succinctly conveys that. While you can just
else ifa bunch of times, you have to read all the way through to make sure there’s no missingelseetc.It’s not often I need it but when I do then edge cases like this are a real shame.
Any updates on this issue?
In Kotlin,
whenexpression is much better in terms of intuition and usability. https://kotlinlang.org/docs/control-flow.html#when-expressionHoping TS can at least supports what OP mentioned.
What’s the advantage of
over
?
The crux of this was filed at #8934 discussed a bit at #2214, but I think the overall guidance is to write something along the lines of
In your case it would be the following: