MDN states that async iterators have a return method
const asyncIterable = {
[Symbol.asyncIterator]() {
let i = 0;
return {
next() {
const done = i === LIMIT;
const value = done ? undefined : i++;
return Promise.resolve({ value, done });
},
return() {
// This will be reached if the consumer called 'break' or 'return' early in the loop.
return { done: true };
}
};
}
};
However, the Typescript definitions of async iterators require the return method to
- accept an optional value
- return
{value: someValue, done: true}, whereas MDN does not do this.
Here's the TS definition:
interface AsyncIterator<T, TReturn = any, TNext = undefined> {
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
next(...args: [] | [TNext]): Promise<IteratorResult<T, TReturn>>;
return?(value?: TReturn | PromiseLike<TReturn>): Promise<IteratorResult<T, TReturn>>;
throw?(e?: any): Promise<IteratorResult<T, TReturn>>;
}
Can someone explain the discrepancy? How does return work?
MDN, however authoritative, is not the source of truth when it comes to language specifications. TypeScript follows the ECMAScript spec, in this instance, the definition of the
AsyncIteratorinterface (as@@asyncIteratorwell-known symbol is a method that returns anAsyncIterator).Table 76 and 77 of the spec provide, respectively, the required and optional properties of the interface:
next,return, andthrow. We are interested in what the spec has to say about the parameters of the second one:Note the last part of the first sentence — here is where the
TReturn | PromiseLike<TReturn>comes from. Then note the second sentence — this is why the parameter is optional.As you can also see from the above, the
returnmethod returns an object implementing theIteratorResultinterface which is defined to have adoneboolean and avalueunrestricted property. Both properties are not considered optional, but each has a note in table 78 of the spec that allows for either to be missing.However, TypeScript definition for the
IteratorReturnResult(a member of theIteratorResultunion type) does not take into account those notes and marks those properties as required:This has been called into question in issue #8938 on the source repository with the team reasoning being:
and subsequently closed in favor of issue #2983 fixed by PR #30790 with the original request seemingly slipping through the cracks.