Skip to content

Nullish coalescing assignment operator does not narrow correctly #40494

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

Closed
danielrentz opened this issue Sep 11, 2020 · 7 comments · Fixed by #40536
Closed

Nullish coalescing assignment operator does not narrow correctly #40494

danielrentz opened this issue Sep 11, 2020 · 7 comments · Fixed by #40536
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue Help Wanted You can do this Rescheduled This issue was previously scheduled to an earlier milestone

Comments

@danielrentz
Copy link

TypeScript Version: 4.0.2

Search Terms: nullish coalescing possibly undefined

Code

let x: string | undefined;

let a: string | undefined;
a ??= "x";
a.length;

let b: string | undefined;
b ??= x;
b.length;

let c: string | undefined;
c = c ?? x ?? "x";
c.length;

let d: string | undefined;
d ??= x ?? "x";
d.length;

Expected behavior:
a.length passes, b.length fails (b undefined), c.length passes, d.length passes, because it becomes a string

Actual behavior:
d.length fails because not narrowed to string.

Playground Link: https://www.typescriptlang.org/play?#code/DYUwLgBAHgXBDOYBOBLAdgcwgHwgVzQBMQAzdEQgbgChrRIBDORVTHfI08q6hiAfn4BeCACIoomgwB0oTGAAWNOuAgAjZsnRZcBYmTQUaagcOjHZIeUtr0IAY02sdHfdxr2IIz4OimxEh6W1sp2hE7a7HpchjyEpiJQ-uKS1ITBGIo0QA

Related Issues: none found

@danielrentz danielrentz changed the title Nullish coalescing shorthand operator does not narrow correctly Nullish coalescing assignment operator does not narrow correctly Sep 11, 2020
@RyanCavanaugh RyanCavanaugh added Bug A bug in TypeScript Help Wanted You can do this labels Sep 11, 2020
@hoangpham95
Copy link
Contributor

hoangpham95 commented Sep 12, 2020

I'd like to take a look into this bug :)

@danielrentz
Copy link
Author

Btw, same problem arises with the ||= operator.

@Kingwl
Copy link
Contributor

Kingwl commented Sep 14, 2020

Seems caused by control flow bind.

Current flow is

 Branch ┬ True (d) ───────────────────────────────╮             ──────────┬ Start  
        ├ True (x) ───────────────────────────────╫───────────┬ False (d) ╯   
        ├──────────────────────────                 False (x) ╯               
        ├ True (d ??= x ?? "x") ─┬ Assignment (d) ╯                           
        ╰ False (d ??= x ?? "x") ╯ 

The True(x) branch has been ignored.

@eventualbuddha
Copy link

I independently ran into this bug and confirmed that my reduced test case fails in 4.1.4 but passes with the playground for #40536:

let a: number | undefined
let b: number | undefined

// TS fails to infer that `a` must be `number`, so `a + 1` errors with:
// Object is possibly 'undefined'. (2532)
a ??= b ?? 1
console.log(a + 1)

// Should be equivalent but without the assignment to `a`, but this works.
console.log((a ?? b ?? 1) + 1)

Is there any reason that fix can't be merged yet?

@stevenwdv
Copy link

stevenwdv commented Aug 22, 2022

I think this should be reopened (or I could create a new issue, let me know).

Take the following code snippet, where there is a bug (?? should have been ||).

let elem!: Element;

let selector1 =
    (elem.hasAttribute('name') && `[name='${elem.getAttribute('name')!}']`)
    ?? elem.tagName;
const s1: string = selector1;  // Correctly reports that false is not assignable to string

let selector2;
selector2 = elem.hasAttribute('name') && `[name='${elem.getAttribute('name')!}']`;
selector2 ??= elem.tagName;
const s2: string = selector2;  // No error as selector2 has been incorrectly narrowed to string, where there should be!!

It seems as though ??= incorrectly works identical to ||= now.

Playground link

Or is this #40359?

@sandersn
Copy link
Member

Sounds a bit more like #40359. You might try to narrow down which version of typescript first exhibited the failure, if it's a regression.

@stevenwdv
Copy link

@sandersn Just checked, it's not a regression, the problems was there in the first version supporting ??=. I'll add the comment to #40359.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue Help Wanted You can do this Rescheduled This issue was previously scheduled to an earlier milestone
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants