能否在TypeScript映射类型中筛选自有/非自有属性?
TypeScript:如何提取类实例的自有属性类型
之前的方案靠过滤函数类型来提取类实例属性,但现在需要不依赖属性类型判断,只保留类实例的自有属性(即直接定义在实例上的属性,排除原型链上的成员)。比如下面的Foobar类,希望ClassProperties类型仅保留value和callback,排除原型上的do方法:
class Foobar { public readonly value = 1; public readonly callback = () => {}; public do() { } } // 待实现的类型 type ClassProperties<C extends new(...args: readonly unknown[]) => unknown> = /* 实现代码 */ const foobar = new Foobar() const data: ClassProperties<typeof Foobar> = {...foobar} data.value // 可正常访问 data.callback // 可正常访问 // @ts-expect-error, "property does not exists" data.do
实现方案
可以通过对比实例类型和类原型类型的键集合,筛选出仅属于实例的自有属性:
type ClassProperties<C extends new (...args: any[]) => any> = { [K in keyof InstanceType<C> as K extends keyof C['prototype'] ? never : K]: InstanceType<C>[K] }
原理解析
InstanceType<C>:获取类C的实例类型C['prototype']:获取类C的原型类型K extends keyof C['prototype'] ? never : K:过滤掉那些存在于原型上的键,只保留实例自身的属性键- 最后将筛选后的键映射为对应的属性类型
用Foobar类测试时,ClassProperties<typeof Foobar>会准确包含value和callback,而原型上的do方法会被排除,完全符合需求。
额外说明
如果类的原型上定义了非方法属性,这个方案同样会排除它们,完全贴合“自有属性”的定义——只有直接挂载在实例对象上的属性才会被保留。
内容的提问来源于stack exchange,提问作者shau-kote
相关产品推荐
相关产品推荐

