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

如何从构造函数或原型推断类/实例类型?附装饰器示例

从原型反向推导类/实例类型(装饰器场景)

我明白你在写属性装饰器时遇到的困扰——拿到原型对象后,没法自动推断出对应的类构造函数类型或实例类型对吧?这其实是因为TypeScript对constructor属性的默认类型推断比较保守,我们只需要做一点类型修正就能解决问题。

先理清核心关系

首先明确几个关键概念的对应关系:

  • 实例类型:比如User类的实例类型就是User本身
  • 构造函数类型:typeof User,也就是能创建User实例的构造函数,我们可以用自定义类型来描述它:
    // 定义通用构造函数类型:接受任意参数,返回T类型实例
    type Constructor<T = {}> = new (...args: any[]) => T;
    
  • 原型对象:User.prototype的类型就是实例类型User,因为实例会继承原型的属性和方法

修正装饰器的类型推断

你的原代码里,装饰器的参数写法有点问题——属性装饰器的第一个参数是完整的原型对象,不是解构后的{ constructor }。我们调整一下写法,就能正确推导类型:

完整示例代码

// 先定义构造函数类型
type Constructor<T = {}> = new (...args: any[]) => T;

// 正确的属性装饰器实现
const Prop = <T>(target: T, propertyKey: string | symbol) => {
  // 把原型的constructor断言为对应类的构造函数类型
  const classConstructor = target.constructor as Constructor<T>;

  // 现在你可以自由使用类类型和实例类型了:
  console.log(`正在装饰${classConstructor.name}类的${String(propertyKey)}属性`);
  
  // 创建实例(类型自动推断为T,也就是User)
  const userInstance = new classConstructor();
  // 访问类的静态属性/方法(如果有的话)
  // classConstructor.staticMethod();
};

// 用户侧代码
class User {
  @Prop
  photos: string[];
}

为什么要做类型断言?

TypeScript默认把所有对象的constructor属性类型推断为Function,这是因为Object.prototype.constructor的基础类型就是Function。但我们知道,原型对象的constructor肯定指向它所属的类,所以用as Constructor<T>断言后,就能获得完整的类构造函数类型信息。

额外:如果需要更严谨的类型约束

如果你想避免类型断言,也可以让装饰器的泛型参数直接绑定构造函数类型,不过这种写法需要用户手动传入类:

const Prop = <C extends Constructor>(constructor: C) => {
  return (target: InstanceType<C>, propertyKey: string | symbol) => {
    console.log(`装饰${constructor.name}类的${String(propertyKey)}属性`);
  };
};

class User {
  @Prop(User)
  photos: string[];
}

不过这种写法不如第一种简洁,一般推荐第一种方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 09:17:36