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

TypeScript递归深度Pick类型实现:获取所有包含get方法的嵌套类

问题分析

你的核心需求是实现一个递归类型DeepPickProperties,能深度筛选出嵌套结构中所有继承自Service的类属性。原尝试的报错原因主要有两个:

  1. 未定义Constructor类型:代码中使用了Constructor但未提前声明,TypeScript无法识别。
  2. 递归逻辑错误:PickProperties<T[K], P>[keyof T[K]]的写法不符合类型操作逻辑,无法正确递归提取嵌套属性。

解决方案

根据你期望Repositories包含shop和book的需求,提供两种实现方式,可根据实际场景选择:


方式一:保留嵌套结构,仅筛选符合条件的属性路径

这种方式会保留原对象的层级结构,只保留属性值为Service子类的属性,并递归处理嵌套内容:

abstract class Service { 
  public abstract get(id?: string): null; 
} 
class BookService extends Service { 
  public get = (id: string) => null 
} 
class ShopService extends Service { 
  book = new BookService(); 
  public get = (id: string) => null 
} 
class Services { 
  shop = new ShopService(); 
}

// 辅助类型:提取当前类型中所有属性值符合P的键
type MatchingKeys<T, P> = {
  [K in keyof T]: T[K] extends P ? K : never;
}[keyof T];

// 递归实现深度筛选
type DeepPickProperties<T, P> = {
  [K in MatchingKeys<T, P>]: DeepPickProperties<T[K], P>;
};

// 测试类型
type Repositories = DeepPickProperties<Services, typeof Service.prototype>;
// Repositories 类型为:{ shop: { book: {} } }

方式二:扁平所有符合条件的属性到顶层

这种方式会把所有嵌套层级中符合条件的属性统一提取到顶层,形成扁平结构,方便直接访问:

abstract class Service { 
  public abstract get(id?: string): null; 
} 
class BookService extends Service { 
  public get = (id: string) => null 
} 
class ShopService extends Service { 
  book = new BookService(); 
  public get = (id: string) => null 
} 
class Services { 
  shop = new ShopService(); 
}

// 辅助类型:提取当前类型中所有属性值符合P的键
type MatchingKeys<T, P> = {
  [K in keyof T]: T[K] extends P ? K : never;
}[keyof T];

// 辅助类型:递归收集所有嵌套层级中符合条件的键
type AllMatchingKeys<T, P> = 
  MatchingKeys<T, P> | 
  { [K in keyof T]: T[K] extends object ? AllMatchingKeys<T[K], P> : never }[keyof T];

// 辅助类型:获取嵌套属性的实际类型
type GetNestedType<T, K extends PropertyKey> = 
  K extends keyof T ? T[K] : 
  T extends object ? GetNestedType<T[keyof T], K> : 
  never;

// 递归实现深度筛选并扁平到顶层
type DeepPickProperties<T, P> = {
  [K in AllMatchingKeys<T, P>]: GetNestedType<T, K>;
};

// 测试类型
type Repositories = DeepPickProperties<Services, typeof Service.prototype>;
// Repositories 类型为:{ shop: ShopService; book: BookService }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 16:24:07