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

TypeScript装饰器包装类如何访问原类静态成员?

解决TypeScript装饰器中访问原类静态成员的类型错误

这个问题我之前也碰到过——核心是TypeScript的类型系统没自动识别到你通过Object.assign复制过去的静态成员,再加上装饰器的类型定义没跟上运行时的操作。下面给你两种针对性的解决思路,按需选择:

情况1:Wrapper需要继承原类的实例成员

如果你的装饰器只是想增强原类的功能(比如重写方法、添加新逻辑),可以让Wrapper直接继承原类,同时通过泛型让TypeScript识别静态成员:

function decorator<T extends { new(...args: any[]): any }>(opts?: any) {
  return function (Class: T) {
    // 让Wrapper继承原类,保留实例成员
    class Wrapper extends Class {
      // 这里添加你的装饰器逻辑,比如重写方法
      someNewMethod() {
        return "enhanced";
      }
    }
    // 运行时复制原类的静态成员到Wrapper
    Object.assign(Wrapper, Class);
    // 断言返回类型为原类构造函数类型,让TS识别静态成员
    return Wrapper as T;
  };
}

class SmthImpl { 
  static readonly staticConst = 7; 
  instanceProp = 42;
}

const Smth = decorator()(SmthImpl);

// 现在访问静态成员不会报错
console.log(Smth.staticConst); // 7
// 实例同时拥有原类和Wrapper的成员
const instance = new Smth();
console.log(instance.instanceProp); // 42
console.log(instance.someNewMethod()); // "enhanced"

情况2:Wrapper是完全独立的类(不需要继承原类实例)

如果你的Wrapper是全新的类,只是需要复用原类的静态成员,可以通过交叉类型让TypeScript同时识别Wrapper的构造函数和原类的静态成员:

function decorator<T extends { new(...args: any[]): any }>(opts?: any) {
  return function (Class: T) {
    class Wrapper {
      // 自定义Wrapper的实例逻辑
      constructor() {
        this.OriginalInstance = new Class();
      }
      OriginalInstance: InstanceType<T>;
      wrapperMethod() {
        return "wrapper logic";
      }
    }
    // 运行时复制原类静态成员
    Object.assign(Wrapper, Class);
    // 返回交叉类型:Wrapper构造函数 + 原类构造函数的静态成员
    return Wrapper as typeof Wrapper & T;
  };
}

class SmthImpl { 
  static readonly staticConst = 7; 
  instanceMethod() {
    return "original method";
  }
}

const Smth = decorator()(SmthImpl);

// 静态成员正常访问
console.log(Smth.staticConst); // 7
// 实例使用Wrapper的自定义逻辑
const instance = new Smth();
console.log(instance.wrapperMethod()); // "wrapper logic"
console.log(instance.OriginalInstance.instanceMethod()); // "original method"

为什么原来的方法不行?

你之前用Object.assign(Smth, SmthImpl)是正确的运行时操作,但TypeScript的类型推断是基于变量声明时的类型(也就是typeof Wrapper),它不会自动因为你后续的Object.assign更新变量类型。所以必须通过泛型捕获原类类型 + 类型断言/交叉类型,让TypeScript知道返回的构造函数包含原类的静态成员。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:28:51