Skip to content

Allow == null to narrow unknown to null | undefined #32798

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
ericyhwang opened this issue Aug 9, 2019 · 6 comments
Closed

Allow == null to narrow unknown to null | undefined #32798

ericyhwang opened this issue Aug 9, 2019 · 6 comments
Labels
Bug A bug in TypeScript
Milestone

Comments

@ericyhwang
Copy link

TypeScript Version: typescript@3.6.0-dev.20190809

Search Terms: unknown, type guard, double-equals, ==, null

Code

Minimal repro case:

export function test(v: unknown) {
  let nullOrUndefined: null | undefined;
  if (v === null || v === undefined) {
    // This works, as `v` is narrowed to `null | undefined`.
    nullOrUndefined = v;
  }
  if (v == null) {
    // Error: Type 'unknown' is not assignable to type 'null | undefined'.
    nullOrUndefined = v;
  }
}

A more practical use-case for the narrowing would be something like this:

if (typeof v === 'string' || v == null) {
  // v should be `string | null | undefined` in here.
  if (v) {
    // v is a non-empty string
    doSearch(v);
  } else {
    // v is empty string, null, or undefined
    clearSearch();
  }
}

Expected behavior:

v == null narrows an unknown type to null | undefined, same as v === null || v === undefined does.

Reading the ECMAScript spec on ==, I believe that == null will guarantee that the value is either null or undefined. == undefined would do the same thing, though linters generally prefer the shorter == null.

Actual behavior:

Compile error:

src/index.ts:11:5 - error TS2322: Type 'unknown' is not assignable to type 'null | undefined'.
  Type 'unknown' is not assignable to type 'null'.

11     nullOrUndefined = v;
       ~~~~~~~~~~~~~~~

Found 1 error.

Playground Link: https://www.typescriptlang.org/play/#code/KYDwDg9gTgLgBAMwK4DsDGMCWEVxsAZxgAoA3ALjlQGsUIB3FASjgG8AoOOAG2HhSTduAeSgBVFABNgCTCmCTKAoXAA+VKTLkKA3JziYEcMnAC85uMu5r1pMxdTTZ8ySw5cuAek9wAKgAtMAjh6aGoCADp9LitRCSdtSTM4Uj0uAF99Q2M7Cys3aLhvPwBPMGA4AHIaOkZKg2C6eABDAgJMAHMUZoAjXjwIPDKKyqs1DQSXSqiPS0ERcU1nBWTU-UzMoA

Related Issues:

@ericyhwang
Copy link
Author

I'd be interested in submitting a PR for this, by the way.

Looking at checker.ts, narrowTypeByEquality already has handling for == null. Without having cloned down the code for testing, my guess: Perhaps getTypeWithFacts might not be narrowing down unknown based on TypeFacts.EQUndefinedOrNull?

@jack-williams
Copy link
Collaborator

jack-williams commented Aug 10, 2019

@ericyhwang I think looking at the changes associated with #26941 is a good place to start—that added a new code path for unknown and ===. The right fix might be to split the code path for === and ==.

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Aug 12, 2019
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Aug 12, 2019
@jack-williams
Copy link
Collaborator

@ericyhwang Are you working on this? I think it's a relatively simple fix, but it would also be nice for you to get a contributor badge.

Do you want to sketch out the solution here together and then you can open a PR?

@ericyhwang
Copy link
Author

@jack-williams Ah, I thought bugs needed a help-wanted label first. Haven't started beyond initially looking at the code.

I'm still interested, though I may not have work-week time for a few weeks. If it's pretty simple, I might treat it like a mini weekend project and do it on my own time.

@jack-williams
Copy link
Collaborator

Oh yeah, forgot about that label. Well I'm sure @RyanCavanaugh would be happy to accept a PR on this given that it's on the backlog.

I'll leave it in your hands, but if you have any Q's just drop them in this issue.

@lkho
Copy link

lkho commented Feb 26, 2020

hi everyone, I faced this same compilation error TS2322 (without strictNullChecks)

Playground:
https://www.typescriptlang.org/play/?strictNullChecks=false&ts=3.8-Beta#code/GYVwdgxgLglg9mABMAjACgB4C5EGcoBOMYA5gJQ5ggC2ARgKYGIDeAUIojMIpogLx9EVADbCyLdh0QF6UEASQYA3JIC+kmXIVCQoletahIsBMgBMmHPiKlEAHx2iKj4RI5ceGfgJfi2U6Vl5RRUOdQ5NYJd9ViA

Is it the same problem discussing in this thread?

Compilation error:
line 3:

(parameter) x: string
Type 'string' is not assignable to type 'number'.(2322)

line 10:

(parameter) x: string
Type 'string' is not assignable to type 'null'.(2322)

However, I saw from the AST viewer, both computed type of x at line 3 is never and line 10 is null, which are both correct (if strictNullChecks).

jespino added a commit to jespino/TypeScript that referenced this issue Aug 6, 2021
…guard

Co-authored-by: Hossein <hahmadia@users.noreply.github.com>
jespino added a commit to jespino/TypeScript that referenced this issue Aug 6, 2021
…guard

Co-authored-by: Hossein <hahmadia@users.noreply.github.com>
hahmadia added a commit to hahmadia/TypeScript that referenced this issue Sep 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript
Projects
None yet
Development

No branches or pull requests

4 participants