Skip to content

Iterator result of Iterable or AsyncIterable inferred to any  #33932

Closed

Description

@ikokostya

TypeScript Version: 3.7.0-dev.20191010

Search Terms:

Iterable, AsyncIterable, Iterator, IteratorResult

Code

Synchronous iterators:

declare let syncIterable: Iterable<number>;
let res = syncIterable[Symbol.iterator]().next();
let value = res.value;

Asynchronous iterator:

declare let asyncIterable: AsyncIterable<number>;

(async () => {
    let res = await asyncIterable[Symbol.asyncIterator]().next();
    let value = res.value;
});

Expected behavior:

In both cases value has number type.

Actual behavior:

Variable value has any type.


Investigation

Type IteratorResult has two type parameters T and TReturn:

type IteratorResult<T, TReturn = any> = IteratorYieldResult<T> | IteratorReturnResult<TReturn>;

Because by default TReturn is any (interface Iterable has only one type parameter), we got number | any type, which is narrowed to any.

There are two problems:

  • There is no way to specify TReturn type parameter for IterableIterator and AsyncIterableIterator types.
  • Current behavior is unsafe.

Playground Link:

https://www.typescriptlang.org/play/index.html?ssl=3&ssc=23&pln=1&pc=1#code/CYUwxgNghgTiAEEQBd4GcCeA7MBJZIMUARkgFzz6ElIA8WArgLbGEB8A3AFBKpxrwAvOmx4CRUiADaAZQwsA9hAB0AS3FRkCmAF0AFAEplWEAA9kh7r3gA3KBAYJh-ZXYcgOQA

Related Issues:

#2983

Activity

  1. ikokostya commented on Oct 10, 2019

    @ikokostya
    ContributorAuthor

    With explicit check done property of IteartorResult:

    declare let syncIterable: Iterable<number>;
    let res = syncIterable[Symbol.iterator]().next();
    if (!res.done) {
        res.value // number
    } else {
        res.value // any
    }
  2. bterlson commented on Feb 8, 2020

    @bterlson
    Member

    In addition to also wanting the fix suggested above (plumbing TReturn and TNext from AsyncIterableIterator to IteratorResult), I wonder if any is the best type? When I see an any I don't suspect I need to narrow, I suspect I've done something wrong. undefined could be a better default, though I haven't considered this at length.

  3. rbuckton commented on Dec 16, 2020

    @rbuckton
    Contributor

    This is a duplicate of 33353. Also, your expected behavior is incorrect. Without checking done, you cannot guarantee that value is a number:

    const numbers: number[] = [];
    const value = numers[Symbol.iterator]().next().value;
    console.log(value); // undefined

    While the correct result should be number | undefined, but may be a significant breaking change.

  4. added
    DuplicateAn existing issue was already created
    and removed
    Needs InvestigationThis issue needs a team member to investigate its status.
    RescheduledThis issue was previously scheduled to an earlier milestone
    on Dec 16, 2020
  5. ikokostya commented on Dec 16, 2020

    @ikokostya
    ContributorAuthor

    Duplicate of #33353

  6. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

DuplicateAn existing issue was already created

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions