Type narrowing not working properly for unions in let declarations #48038
Copy link
Copy link
Closed
Description
Bug Report
When you type a variable with a union type, typescript is too aggressive while narrowing it down. Specifically, it only considers assignments in the "main" flow, and ignores any other possibility.
🔎 Search Terms
let, type guard, type narrowing, never
🕗 Version & Regression Information
I've tried with different TS versions starting in 3., and it happens in all of them. I also tried with nightly (v4.7.0-dev.20220215)
⏯ Playground Link
Playground link with relevant code
💻 Code
let foo: string | number = 42;
function bar() {
foo = '42';
}
bar();
// foo = '42'; // if we uncomment this, we're fine
if (typeof foo === 'string') {
foo.includes('x'); // TS Error: property 'includes' does not exist on type 'never'
}🙁 Actual behavior
TS shouldn't be so eager to narrow the type to never.
🙂 Expected behavior
Don't narrow unions based on assignments. Or, if it's not too hard to implement, do it only when you can be absolutely certain. I.e., no function after the assignment that caused the type narrowing.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
[-]Type guards not working properly for unions in let declarations[/-][+]Type narrowinf not working properly for unions in let declarations[/+][-]Type narrowinf not working properly for unions in let declarations[/-][+]Type narrowing not working properly for unions in let declarations[/+]MartinJohns commentedon Feb 25, 2022
Duplicate of #9998.
Assignments within closures are not recognized, so according to TypeScript the only value ever assigned is
42, anumber, and trying to compare this to astringmakes no sense. You can prevent the narrowing upon assignment (which is intended) using a type assertion:lgenzelis commentedon Feb 25, 2022
Martin Johns (@MartinJohns) #9998 was a pleasure to read, and definitely drove the point home for me that we have to "endure" the bad cases of the optimistic approach, because the pessimistic one would be a nightmare. Thank you for that.
MartinJohns commentedon Feb 25, 2022
You're probably the first one to actually read the issue after being linked to it.
danny-does-stuff commentedon May 15, 2024
I am currently switching from Flow to TS, and FWIW once I understood that Flow was taking the pessimistic approach, it rarely bothered me, even though most of my functions were pure. I guess it's just part of the learning curve of switching!