【问题标题】:Typescript: Typeguard Symbol.iterator打字稿:类型保护 Symbol.iterator
【发布时间】:2021-03-25 09:24:27
【问题描述】:

我正在尝试编写一个接受 Iterable<T> 或 `AsyncIterable 的函数并对其进行映射:

function map<T, U>(
  fn: (item: T) => U,
  items: Iterable<T> | AsyncIterable<T>,
): Iterable<U> | Iterable<U> & AsyncIterable<U> {
  async function* asyncMapper() {
    for await (const item of items) {
      yield fn(item);
    }
  }

  if (!items[Symbol.iterator]) {
    return asyncMapper()
  }

  return {
    *[Symbol.iterator]() {
      for (const item of items) {
        yield fn(item);
      }
    },

    [Symbol.asyncIterator]: asyncMapper,
  };
}

See playground

它的要点是,如果项目实现Symbol.iterator,我们将返回一个可以同步迭代异步的迭代。但是,如果我们不这样做,我们将只返回异步迭代。

问题是由于错误,我无法对Symbol.iterator 的存在进行类型保护:

错误 TS7053: 元素隐式具有 any 类型,因为 symbol 类型的表达式不能用于索引类型 Iterable&lt;T&gt; | AsyncIterable&lt;T&gt;

有谁知道如何对Symbol.iterator 进行打字,或者我在这里做错了什么?

【问题讨论】:

    标签: typescript iterable typeguards


    【解决方案1】:

    使用用户定义的类型保护:

    function isIterable(x: any): x is Iterable<unknown> {
      return Symbol.iterator in x;
    }
    
    function map<T, U>(
      fn: (item: T) => U,
      items: Iterable<T> | AsyncIterable<T>
    ): Iterable<U> | AsyncIterable<U> {
      async function* asyncMapper() {
        for await (const item of items) {
          yield fn(item);
        }
      }
    
      if (!isIterable(items)) {
        return asyncMapper()
      }
    
      return {
        *[Symbol.iterator]() {
          for (const item of items) {
            yield fn(item);
          }
        },
    
        [Symbol.asyncIterator]: asyncMapper,
      };
    }
    

    Playground link

    【讨论】:

      猜你喜欢
      • 2017-05-18
      • 2018-06-08
      • 2018-07-13
      • 1970-01-01
      • 1970-01-01
      • 2020-05-11
      • 1970-01-01
      • 1970-01-01
      • 2020-12-24
      相关资源
      最近更新 更多