Typescript: IteratorResult should be a discriminated union

Created on 26 Nov 2018  路  10Comments  路  Source: microsoft/TypeScript

Suggestion

Current definition of IteratorResult demands value to be provided regardless of whether done is true or false.

Suggestion: Change IteratorResult to something like this

type IteratorResult<T> =
  { readonly done: true } |
  { readonly done: false, readonly value: T }

Use Cases

I am currently trying to build a custom async iterator that cannot be done with async generator, it is absurd that I had to provide some value when iteration is done.

Checklist

My suggestion meets these guidelines:

  • [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • [x] This wouldn't change the runtime behavior of existing JavaScript code
  • [x] This could be implemented without emitting different JS based on the types of the expressions
  • [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • [x] This feature would agree with the rest of TypeScript's Design Goals.
Duplicate

Most helpful comment

duplicate of #11375?

All 10 comments

I think I just force cast to as any or sth.

Edit:
Found in my code, lol

                        //We passed the end of the last page
                        return {
                            done : true,
                            value : undefined as any,
                        };

@AnyhowStep Yeah, that was my workaround too. But I think it shouldn't be, hence the request.

duplicate of #11375?

According to the spec and MDN the value property may (but is not required to) be present when done is true.
I think the proper typing should be

type IteratorResult<T> =
  { readonly done: true, readonly value?: T } |
  { readonly done: false, readonly value: T }

or even:

type IteratorResult<T> =
  { readonly done: true, readonly value?: any } |
  { readonly done: false, readonly value: T }

@rbuckton think we've got enough infrastructure in place to be able to try this lib change yet?

@hwanders If we were to follow the spec, done should be optional:

type IteratorResult<T> =
  { readonly done: true, readonly value?: T } |
  { readonly done?: false, readonly value: T }

For reference, @KSXGitHub is talking about this: https://tc39.github.io/ecma262/#sec-iteratorresult-interface (emphasis added):

If the end of the iterator was reached done is true. If the end was not reached done is false and a value is available. _If a done property (either own or inherited) does not exist, it is consider to have the value false._

And this (emphasis added):

If done is false, this is the current iteration element value. If done is true, this is the return value of the iterator, if it supplied one. If the iterator does not have a return value, value is undefined. In that case, _the value property may be absent from the conforming object if it does not inherit an explicit value property._

There is, however, nothing that indicates done or value are read-only.

@rbuckton Although the spec does not _demand_ the properties to be either writable or read-only, not making them read-only makes it impossible to use a read-only object (e.g. frozen) as an IteratorResult. The way I see it, you are not supposed to modify these properties unless stated otherwise.

This issue has been marked as a duplicate and has seen no activity in the last day. It has been closed automatic house-keeping purposes.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bgrieder picture bgrieder  路  3Comments

wmaurer picture wmaurer  路  3Comments

CyrusNajmabadi picture CyrusNajmabadi  路  3Comments

DanielRosenwasser picture DanielRosenwasser  路  3Comments

Antony-Jones picture Antony-Jones  路  3Comments