在 Typescript 中使用 AsyncIterator – 必需选项

pan*_*ter 2 javascript node.js async-await typescript async-iterator

考虑来自 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);
   }
})();

Run Code Online (Sandbox Code Playgroud)

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

{
  "compilerOptions": {
    "lib": ["es2016", "esnext.asynciterable"],
    "target": "es2016"
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

TS手册中提到的几个注意事项,其中没有一个能解决我的问题。奇怪的是,迭代异步生成器工作正常。

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

Pat*_*rts 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 });
      }
    };
  }
};
Run Code Online (Sandbox Code Playgroud)

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

interface IteratorResult<T> {
  done: boolean;
  value: T;
}
Run Code Online (Sandbox Code Playgroud)

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 });
      }
    };
  }
};
Run Code Online (Sandbox Code Playgroud)