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

TypeScript实现MongoDB风格数组Unwind泛型函数的类型定义问题

实现带类型推导的MongoDB风格unwind函数(TypeScript)

先看修正后的完整可运行代码,再拆解解决你的两个核心问题:

describe('unwindByKey', () => {
  // 解决问题1和2的类型定义:移除指定数组键,同时将该键的类型转为数组元素类型
  type UnwindItemType<T, K extends keyof T> = Omit<T, K> & {
    [P in K]: T[K] extends (infer U)[] ? U : T[K]
  }

  // 修正后的函数:约束传入的key必须对应对象中的数组属性,返回类型自动推导
  function unwindByKey<T extends {}, K extends keyof T & (T[K] extends any[] ? K : never)>(
    items: T[],
    key: K
  ): UnwindItemType<T, K>[] {
    return items.reduce((accum, item) => {
      const { [key]: keyItems, ...itemRest } = item;
      const unwoundItems = keyItems.map((keyItem) => ({
        ...itemRest,
        [key]: keyItem
      })) as UnwindItemType<T, K>[];
      return [...accum, ...unwoundItems];
    }, [] as UnwindItemType<T, K>[]);
  }

  // 示例测试
  interface DataItem {
    a: number;
    b: number[];
  }

  // 现在UnwoundDataItem会自动推导为 {a: number; b: number}
  type UnwoundDataItem = UnwindItemType<DataItem, 'b'>;

  const data: DataItem[] = [
    { a: 0, b: [0, 1, 2] },
    { a: 1, b: [3, 4, 5] },
  ];

  const expectedData: UnwoundDataItem[] = [
    { a: 0, b: 0 },
    { a: 0, b: 1 },
    { a: 0, b: 2 },
    { a: 1, b: 3 },
    { a: 1, b: 4 },
    { a: 1, b: 5 },
  ];

  test('it works', () => {
    const result = unwindByKey(data, 'b');
    expect(result.length).toBe(expectedData.length);
    expect(result).toEqual(expectedData);
    // 此时result的类型会自动匹配UnwoundDataItem[],类型完全正确
  });
});

核心问题拆解解决

  1. 从输入泛型确定展开后项的类型
    使用TypeScript的infer关键字提取数组元素类型:T[K] extends (infer U)[] ? U : T[K]。这段逻辑会检查T[K]是否为数组类型,若是则提取内部元素类型U,最终将原数组键的类型替换为单个元素类型。

  2. 移除包含嵌套数组的键并替换类型

    • 先用Omit<T, K>移除原对象中指定的数组键,保留其余属性。
    • 再通过映射类型{ [P in K]: ... }重新定义该键的类型为数组元素类型。
    • 最后用&运算符将两部分类型合并,得到展开后的完整对象类型。

额外优化:类型安全约束

函数给泛型K加了约束:K extends keyof T & (T[K] extends any[] ? K : never)。这样能确保调用时传入的key必须是对象中值为数组的属性,避免传入非数组键导致的运行时错误,同时增强IDE的类型提示。

内容的提问来源于stack exchange,提问作者cyrf

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 08:20:47