在Typescript中使用AsyncIterator –必需的选项

时间:2019-07-16 18:31:18

标签: javascript node.js typescript async-await async-iterator

考虑基本的AsyncIterator Example from MDN

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.,与目标esnext相同。

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

TS manual提到了几个警告,但没有一个可以解决我的问题。奇怪的是,iterating async generators可以正常工作。

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

1 个答案:

答案 0 :(得分:1)

深入研究问题之后,似乎是由于这里存在多个问题。

异步迭代器不能依赖其上下文(例如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 });
      }
    };
  }
};

现在问题似乎与第二个return语句中缺少value有关。因为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 });
      }
    };
  }
};