2

考虑 MDN 中的这个基本AsyncIterator 示例

var asyncIterable = {
  [Symbol.asyncIterator]() {
    return {
      i: 0,
      next() {
        if (this.i < 3) {
          return Promise.resolve({ value: this.i++, done: false });
        }

        return Promise.resolve({ done: true });
      }
    };
  }
};

(async function() {
   for await (let num of asyncIterable) {
     console.log(num);
   }
})();

在节点 10.16.0 上运行它可以正常工作。但是,我似乎无法让它通过 Typescript 运行。使用这个 tsconfig:

{
  "compilerOptions": {
    "lib": ["es2016", "esnext.asynciterable"],
    "target": "es2016"
  }
}

导致The type returned by the 'next()' method of an async iterator must be a promise for a type with a 'value' property.错误 target 的相同错误esnext

如果我完全删除该target选项,我会得到一个Type '{ [Symbol.asyncIterator](): { i: number; next(): Promise<{ done: boolean; }>; }; }' is not an array type or a string type.

TS 手册提到了几个警告,但没有一个可以解决我的问题。奇怪的是,迭代异步生成器工作正常。

编译此示例需要哪些 tsconfig 选项?

4

1 回答 1

5

在深入研究了这个问题之后,它似乎是由于这里的多个问题造成的。

异步迭代器不能依赖其上下文(例如this.i)来访问不属于AsyncIterator接口的属性。这样做不会在当前版本的 TypeScript 3.6 中编译(即使它在 JavaScript 中运行良好),所以要解决这个问题,我们只剩下:

var asyncIterable = {
  [Symbol.asyncIterator]() {
    let i = 0;
    return {
      next() {
        if (i < 3) {
          return Promise.resolve({ value: i++, done: false });
        }

        return Promise.resolve({ done: true });
      }
    };
  }
};

现在问题似乎与value第二个 return 语句中的缺失有关。因为IteratorResult接口是这样定义的:

interface IteratorResult<T> {
  done: boolean;
  value: T;
}

next()方法必须始终返回一个对象value: number(同样,即使它在 JavaScript 中工作正常),所以最后我们有:

var asyncIterable = {
  [Symbol.asyncIterator]() {
    let i = 0;
    return {
      next() {
        if (i < 3) {
          return Promise.resolve({ value: i++, done: false });
        }

        return Promise.resolve({ value: i, done: true });
      }
    };
  }
};
于 2019-07-16T19:10:55.377 回答