如何从构造函数或原型推断类/实例类型?附装饰器示例
从原型反向推导类/实例类型(装饰器场景)
我明白你在写属性装饰器时遇到的困扰——拿到原型对象后,没法自动推断出对应的类构造函数类型或实例类型对吧?这其实是因为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
相关产品推荐
相关产品推荐

