Использовать AsyncIterator в Typescript - обязательные параметры

Рассмотрим этот базовый пример AsyncIterator из 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 упоминает несколько предостережений, ни одно из которых не может решить мою проблему. Как ни странно, итерация асинхронных генераторов работает нормально.

Какие параметры tsconfig необходимы для компиляции этого примера?

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

Теперь проблема, кажется, связана с 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 });
      }
    };
  }
};
Другие вопросы по тегам