TypeScript中如何通过装饰器实现通用静态构造函数?
使用TypeScript装饰器简化静态
of构造方法的重复代码 问题背景
我习惯用Foo.of()/Foo.from()这类静态构造方法替代new调用的传统类构造函数,觉得这种方式更简洁易读,还支持无点调用。但每个类都手动写一遍of方法会产生大量重复样板代码,比如:
class Foo<T> { constructor(private value: T) {} static of<T>(value: T) { return new Foo(value); } } class Bar<T, U> { constructor(private value1: T, private value2: U) {} static of<T, U>(value1: T, value2: U) { return new Bar(value1, value2); } }
想通过装饰器结合接口的方式,避免每次手动声明of方法,实现类似下面的写法:
type Constructor = new (...args: any) => any; interface Constructable<T extends Constructor> { static of(...args: Parameters<T>): T; } function constructable<T>(constructor: Constructor) { ... } // 使用示例 @constructable class Foo<T> { constructor(private value: T) {} } interface Foo<T> extends Constructable<Foo<T>> {} @constructable class Bar<T, U> { constructor(private value1: T, value2: U) {} } interface Bar<T, U> extends Constructable<Bar<T, U>> {} const foo = Foo.of(10) const bar = Bar.of(10, 20)
解决方案
完全可以通过TypeScript装饰器实现这个需求,同时结合接口完善类型提示,以下是完整实现:
1. 定义装饰器与类型接口
// 通用构造函数类型 type Constructor<T = any> = new (...args: any[]) => T; // 定义Constructable接口,规范静态of方法的类型 interface Constructable<T extends Constructor> { new (...args: Parameters<T>): InstanceType<T>; of(...args: Parameters<T>): InstanceType<T>; } // 实现装饰器:给目标类添加静态of方法 function constructable<T extends Constructor>(constructor: T): Constructable<T> { // 挂载of静态方法,内部复用原构造函数创建实例 constructor.of = function(...args: Parameters<T>): InstanceType<T> { return new constructor(...args); } as typeof constructor.of; // 返回修改后的构造函数,确保类型匹配 return constructor as Constructable<T>; }
2. 给类应用装饰器并扩展类型
@constructable class Foo<T> { constructor(private value: T) {} } // 通过接口扩展Foo的静态类型,让TS识别of方法 interface Foo<T> extends Constructable<typeof Foo> {} @constructable class Bar<T, U> { constructor(private value1: T, private value2: U) {} } interface Bar<T, U> extends Constructable<typeof Bar> {}
3. 测试使用
const foo = Foo.of(10); // 类型自动推导为Foo<number> const bar = Bar.of("hi", 20); // 类型自动推导为Bar<string, number> console.log(foo.value); // 输出10 console.log(bar.value1, bar.value2); // 输出hi 20
额外扩展:支持from方法
如果需要添加from这类静态方法,只需修改接口和装饰器即可:
// 扩展Constructable接口 interface Constructable<T extends Constructor> { new (...args: Parameters<T>): InstanceType<T>; of(...args: Parameters<T>): InstanceType<T>; from(instance: InstanceType<T>): InstanceType<T>; } // 更新装饰器实现 function constructable<T extends Constructor>(constructor: T): Constructable<T> { // 保留of方法 constructor.of = function(...args: Parameters<T>): InstanceType<T> { return new constructor(...args); } as typeof constructor.of; // 添加from方法(示例逻辑:复制实例属性创建新实例) constructor.from = function(instance: InstanceType<T>): InstanceType<T> { return new constructor(...Object.values(instance) as Parameters<T>); } as typeof constructor.from; return constructor as Constructable<T>; }
内容的提问来源于stack exchange,提问作者Adam B.
相关产品推荐
相关产品推荐

