TypeScript如何定义泛型获取类父子实例所有number类型属性的键
实现方案
完整可运行代码如下:
// 工具类型:提取泛型T中值类型为number的属性键 type NumberPropertyKeys<T> = { [K in keyof T]: T[K] extends number ? K : never }[keyof T] class A { foo = 1; xoo = 'abc'; get(): Record<NumberPropertyKeys<this>, number> { const result = {} as Record<NumberPropertyKeys<this>, number>; // 运行时遍历实例属性,过滤出值为number的属性 for (const key in this) { const val = this[key]; if (typeof val === 'number') { result[key as NumberPropertyKeys<this>] = val; } } return result; } } class B extends A { bar = 2; zar = [1, 2, 3]; init() { const res = this.get(); // 此处输入res. 会自动补全 foo、bar 两个属性 console.log(res.foo, res.bar); } }
原理解析
- 工具类型
NumberPropertyKeys:通过映射类型遍历泛型T的所有属性键,对每个属性做类型校验,如果属性值类型是number则保留键名,否则映射为never,最后通过索引访问[keyof T]过滤掉所有never值,得到符合要求的属性键的联合类型。该工具会自动排除函数类型、字符串、数组等非number类型的属性,天然满足过滤get、init、xoo、zar的要求。 - 多态
this类型:父类get方法的返回类型中直接使用this作为泛型参数,TS在处理类继承场景时,会将调用方法的实际实例类型(子类B的实例类型)代入this,而非固定使用父类A的类型,因此可以同时捕获父类和子类的所有属性。 - 运行时逻辑和类型定义对齐:
get方法内部通过for...in遍历实例所有可枚举属性(包含继承自父类的属性),用typeof判断值类型后收集,保证运行时返回的对象和TS推导的类型完全一致,不会出现类型和实际值不符的情况。
内容的提问来源于stack exchange,提问作者Craig
相关产品推荐
相关产品推荐

