You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中为添加的迭代器正确进行类型标注?

为数组字典添加类型安全的迭代器

要实现类型安全的标注,核心是利用TypeScript的泛型和映射类型捕获输入对象的结构,推导迭代器返回值的具体类型。以下是完整的类型标注方案:

完整代码实现

const obj = { x: [1, 2, 3], y: [4, 5, 6], z: ["a", "b", "c"] };
const arr = [
  { x: 1, y: 4, z: "a" },
  { x: 2, y: 5, z: "b" },
  { x: 3, y: 6, z: "c" },
];

// 定义符合IteratorResult规范的结束标识
const DONE: IteratorResult<never, void> = { done: true, value: undefined };

// 用泛型T捕获输入对象的具体结构
const addLongIterator = <T extends Record<string, readonly any[]>>(data: T) => {
  Object.defineProperty(data, Symbol.iterator, {
    value: function () {
      const keys = Object.keys(data) as Array<keyof T>;
      let i = 0;
      return {
        next(): IteratorResult<{ [K in keyof T]: T[K][number] }, void> {
          if (!(i < data[keys[0]].length)) return DONE;
          // 用映射类型标注返回对象的精确类型
          const value = {} as { [K in keyof T]: T[K][number] };
          for (const key of keys) {
            value[key] = data[key][i];
          }
          i++;
          return { done: false, value };
        },
      };
    },
  });

  // 返回类型:原对象类型 + 带具体类型的迭代器
  return data as T & {
    [Symbol.iterator](): Iterator<{ [K in keyof T]: T[K][number] }, void, undefined>;
  };
};

const objIt = addLongIterator(obj);

// 此时objIt的迭代元素会被正确推导为 { x: number; y: number; z: string }
for (const x of objIt) console.log(x);
for (const x of arr) console.log(x);

关键类型标注解析

  1. 泛型约束

    • 用<T extends Record<string, readonly any[]>>定义泛型T,约束输入对象的每个属性都是数组(readonly any[]兼容只读数组场景),同时让TypeScript自动捕获输入对象的具体键名和数组元素类型。
  2. 迭代器元素类型推导

    • 通过映射类型{ [K in keyof T]: T[K][number] }生成迭代器返回的对象类型:遍历T的所有键K,取对应数组T[K]的元素类型T[K][number],最终组合成和数组元素结构完全一致的对象类型。
    • Iterator<ItemType, ReturnType, NextInputType>参数说明:
      • ItemType:迭代器返回的元素类型(即上述映射类型)
      • ReturnType:迭代结束时的返回值类型(这里为void,对应done状态的value为undefined)
      • NextInputType:next()方法接受的参数类型(这里无需参数,所以设为undefined)
  3. 内部变量类型修正

    • 将keys断言为Array<keyof T>,确保遍历的键都是输入对象的合法键,避免类型不匹配。
    • 用映射类型标注value,替代原来的Record<string, any>,保证每个键的类型和对应数组元素严格一致。
  4. 结束标识类型规范

    • 定义DONE为IteratorResult<never, void>,符合TypeScript迭代器结果的官方规范,消除类型歧义。

内容的提问来源于stack exchange,提问作者Adam B.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 01:15:17