1

MDN 声明异步迭代器有一个返回方法

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 };
      }
    };
  }
};

但是,异步迭代器的 Typescript 定义需要该return方法

  1. 接受一个可选值
  2. return {value: someValue, done: true},而 MDN 不这样做。

这是 TS 定义:

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>>;
}

有人可以解释这种差异吗?如何return工作?

4

1 回答 1

3

MDN,无论多么权威,在语言规范方面都不是事实的来源。TypeScript 遵循ECMAScript 规范,在这种情况下,AsyncIterator接口的定义(@@asyncIterator 众所周知的符号是一个返回 的方法AsyncIterator)。

规范的表 76 和 77 分别提供了接口的必需和可选属性:nextreturnthrow。我们对规范对第二个参数的说明感兴趣:

返回的 promise 将使用一个IteratorResult对象来实现,该对象通常具有一个值为 true 的“done”属性,以及一个将值作为返回方法的参数传递的“value”属性。但是,此要求并未强制执行。

注意第一句的最后一部分——这里是 the 的TReturn | PromiseLike<TReturn>来源。然后注意第二句——这就是为什么参数是可选的。

从上面也可以看出,该return方法返回一个实现IteratorResult接口的对象,该接口定义为具有done布尔值和value不受限制的属性。这两个属性都不被认为是可选的,但每个属性在规范的表 78 中都有一个注释,允许丢失任何一个。

IteratorReturnResult但是, (联合类型的成员)的TypeScript 定义IteratorResult没有考虑这些注释并根据需要标记这些属性:

interface IteratorReturnResult<TReturn> {
    done: true;
    value: TReturn;
}

这已在源存储库的问题 #8938中受到质疑,团队推理为:

正如@ivogabe 所指出的,我们需要具有布尔文字类型,以便能够准确地对其进行建模。

随后关闭以支持PR #30790修复的问题 #2983,原始请求似乎从裂缝中溜走。

于 2022-02-27T20:40:51.673 回答