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

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.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:00:38