Assignment narrowing failing to reset in a loop with optional chaining
#57.816 aperta il 17 mar 2024
Metriche repository
- Star
- (48.455 star)
- Metriche merge PR
- (Merge medio 6g 17h) (9 PR mergiate in 30 g)
Descrizione
🔎 Search Terms
assignment narrowing, optional chaining, narrowing to never,
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about assignment narrowing and optional chaining.
⏯ Playground Link
💻 Code
interface Foo { bar: number; }
declare const foos: Foo[];
let prevPrevFoo: Foo | null = null;
let prevFoo: Foo | null = null;
for (const foo of foos) {
while (
foo.bar === prevPrevFoo?.bar && // error!
// --------------------> ~~~
// Property 'bar' does not exist on type 'never'.
foo.bar === prevFoo?.bar
) {
foo.bar++
}
prevPrevFoo = prevFoo;
prevFoo = foo;
}
🙁 Actual behavior
prevPrevFoo is apparently narrowed to null via assignment narrowing, so prevPrevFoo?.bar gives an error that never doesn't have a bar property. But prevPrevFoo is assigned within the loop, so it seems strange that the narrowing persists in that scope.
🙂 Expected behavior
No error, prevPrevFoo should be considered Foo | null inside the loop.
Additional information about the issue
Comes from this SO question. Not sure what's going on here, but it seems quite dependent on the nesting and order of operations. Most things I did to try to reduce it further made the error disappear.
Note that this is not a case of #9998, there's no closure to speak of. And of course we can work around this by opting out of assignment narrowing via let prevPrevFoo = null as Foo | null;. I don't think this is a big deal, but it would be nice to know the cause of this and whether it's a bug, design limitation, or somehow working as intended (and if so, why).