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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 02:24:03