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

如何在TypeScript交叉类型中使用infer?嵌套泛型类型转换问题

解决交叉类型中infer无法解析嵌套泛型的问题

问题说明

我在开发一个关联数据查询构建器,核心需求是把嵌套的泛型类型按照嵌套深度转换成对应维度的数组(比如一级嵌套对应T[],二级对应T[][])。

为了让开发者调用Person.select()时,既能使用原类的get/set方法,又能调用filter()这类专属查询方法,我把原Shape类型转换为QueryShape<..> & MappedShape<..>的交叉类型——其中MappedShape负责将原属性转为映射查询对象,QueryShape提供查询方法。

但现在遇到了问题:infer关键字在交叉类型里无法正常工作。像result、result2能正确推导为string[]、string[][],但result3、result4的类型却是unknown,我预期p.friend.friend的类型应该是Person[][]。

解决方案

问题根源在于交叉类型的歧义——TypeScript直接对交叉类型使用infer时,无法明确该从哪一部分提取泛型参数。我们需要先把交叉类型里的MappedShape部分单独提取出来,再进行递归的数组转换。

修改后的类型工具与完整代码

// 定义查询方法的基础类型
type QueryShape<T> = {
  filter: (predicate: (item: T) => boolean) => void;
  select: () => NestedArray<QueryShape<T> & MappedShape<T>>;
};

// 把原Shape的属性映射为查询对象类型
type MappedShape<T> = {
  [K in keyof T]: T[K] extends object ? QueryShape<T[K]> & MappedShape<T[K]> : T[K];
};

// 从交叉类型里提取出MappedShape部分
type ExtractMappedShape<T> = T extends QueryShape<infer S> & MappedShape<infer S> ? MappedShape<S> : never;

// 递归生成对应嵌套深度的数组类型
type NestedArray<T> = T extends { [K in keyof T]: infer U } 
  ? U extends object 
    ? NestedArray<ExtractMappedShape<U>>[] 
    : U[] 
  : never;

// 示例Person类
class Person {
  name: string;
  friend: Person;

  constructor(name: string) {
    this.name = name;
    this.friend = this; // 简化示例逻辑
  }

  static select(): NestedArray<QueryShape<Person> & MappedShape<Person>> {
    return [] as any;
  }
}

// 使用验证
const result = Person.select().map(p => p.name); // 类型:string[]
const result2 = Person.select().map(p => p.friend.name); // 类型:string[][]
const result3 = Person.select().map(p => p.friend); // 类型:Person[][]
const result4 = Person.select().map(p => p.friend.friend); // 类型:Person[][][]

原理说明

  1. 交叉类型的歧义问题:QueryShape<S> & MappedShape<S>是两种类型的合并结构,直接用infer时,TypeScript无法确定该提取哪部分的泛型参数,只能返回unknown。
  2. ExtractMappedShape的作用:通过明确匹配交叉类型的结构,单独提取出负责属性映射的MappedShape部分,避免递归时被QueryShape里的方法干扰,确保能正确拿到嵌套的属性类型。
  3. 递归数组生成:在NestedArray类型中,先判断属性是否为对象类型,如果是则先提取其MappedShape部分,再递归生成数组类型,从而实现根据嵌套深度生成对应维度的数组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 22:54:56