Skip to content
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

Unable to use done property of IteratorResult to narrow types in typescript 3.6.2 #33241

Closed
brainkim opened this issue Sep 4, 2019 · 3 comments
Assignees
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@brainkim
Copy link

brainkim commented Sep 4, 2019

TypeScript Version: 3.6.2

Search Terms:
async iterator IteratorResult iterable next return throw type narrowing

Code
file: iterator-result.ts

declare const result: IteratorResult<string, number>;
if (!result.done) {
  let value: string = result.value;
  console.log(value);
}

Expected behavior:
The code compiles. Checking the negation of result.done narrows the type of result.value to string.

Actual behavior:

iterator-result.ts(3,7): error TS2322: Type 'string | number' is not assignable to type 'string'.
  Type 'number' is not assignable to type 'string'.

I thought the whole point of strictly typed iterators was that we could use the done to narrow the type of value, but it seems like a late-game change (making IteratorYieldResult.done optional) prevents us from doing this.

I’m fine with having result.done be optional for IteratorYieldResult but this raises the question why we didn’t also allow result.value to be optional in IteratorReturnResult, when it is idiomatic javascript to return { done: true } without a value in custom iterators.

Playground Link:

Typescript 3.6.2 is not available in the playground yet.

Related Issues:
#30790 <- pr which introduced this change.
#2983
#10564
#11375
#27059

@MattiasBuelens
Copy link
Contributor

According to this comment on #27059, this bug only happens when strictNullChecks is off. If you can, you should enable strictNullChecks (or strict).

@brainkim
Copy link
Author

Can confirm, was testing with a plain tsc call which did not enable strict.

@rbuckton
Copy link
Member

This is currently a limitation of control-flow when strictNullChecks is not enabled. The problem is that null and undefined are assignable to a type of true, therefore we cannot remove the done: true discriminant from the union in the negative case of !result.done. Please note that the following conditions do work:

if (result.done) {
  let value: number = result.value;
}
if (result.done === false) {
  let value: string = result.value;
}

@rbuckton rbuckton added Design Limitation Constraints of the existing architecture prevent this from being fixed Working as Intended The behavior described is the intended behavior; this is not a bug and removed Bug A bug in TypeScript labels Oct 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

5 participants