TypeScript中如何获取对象constructor强类型并提取其原型的键?
问题原因
TypeScript 类型系统默认将所有对象的constructor属性类型设定为Function,这是因为 JavaScript 允许运行时修改constructor指向,TS 出于类型安全考虑没有默认推导具体构造函数类型。而Function的prototype类型为any,keyof any的结果就是string | number | symbol,这就是你得到不符合预期结果的核心原因。
解决方案
方案1:显式声明类的 constructor 类型
只需要在类定义中加一行类型声明,不会修改运行时代码,即可拿到强类型的构造函数:
// 调整PrototypeKeys,过滤Object原型上的内置方法,满足普通对象返回never的预期 type PrototypeKeys<T> = T extends { constructor: { prototype: infer P } } ? Exclude<keyof P, keyof Object['prototype']> : never; type ConstructorOf<T> = T extends { constructor: infer C } ? C : never; class Foo { // 显式声明constructor的类型为当前类的构造函数类型 declare constructor: typeof Foo; foo() { return 1; } } const foo = new Foo(); // 结果为 'foo',符合预期 type FooPrototypeKeys = PrototypeKeys<typeof foo>; // 结果为 typeof Foo,符合预期 type FooConstructor = ConstructorOf<typeof foo>; const bar = { foo() { return 1; } }; // 结果为 never,符合预期 type BarPrototypeKeys = PrototypeKeys<typeof bar>;
方案2:非侵入式调整类型逻辑
如果不想修改所有类的定义,且不需要严格区分「实例自身属性」和「原型继承属性」,可以直接简化类型工具:
// 仅对类实例生效,普通对象返回never type PrototypeKeys<T> = T extends object ? T extends Record<string, any> ? Exclude<keyof T, keyof Object['prototype']> : never : never;
这种写法的局限性是无法区分类中定义的实例属性和原型属性,只要是实例可访问的属性都会被返回。
内容的提问来源于stack exchange,提问作者dx_over_dt
相关产品推荐
相关产品推荐

