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

如何用函数/装饰器处理TypeScript类并生成移除首参的新类?

如何实现移除类所有方法第一个参数的TypeScript工具?

当然可以!我们可以通过TypeScript工具类型处理类型层面的接口生成,同时配合运行时函数实现类方法的转换。下面分两部分详细说明:


1. 类型层面:生成移除第一个参数的接口

首先定义一个工具类型,用来移除单个函数的第一个参数:

// 移除函数的第一个参数
type OmitFirstParameter<T> = T extends (first: any, ...rest: infer RestArgs) => infer ReturnType
  ? (...rest: RestArgs) => ReturnType
  : T;

接着,我们可以用这个工具类型遍历类的所有方法,生成新的类型:

// 转换整个类的所有方法,移除每个方法的第一个参数
type ClassWithoutFirstParam<T> = {
  [MethodName in keyof T]: OmitFirstParameter<T[MethodName]>;
};

现在你就可以用这个类型来定义接口C了:

// 原类定义
class A {
  public aCall(a: any, payload: string): void {}
  public bCall(a: any, payload: number): void {}
  public cCall(a: any): void {}
}

// 生成移除第一个参数的接口
interface C extends ClassWithoutFirstParam<A> {}

// 此时C的类型等价于:
// interface C {
//   aCall(payload: string): void;
//   bCall(payload: number): void;
//   cCall(): void;
// }

2. 运行时层面:生成移除第一个参数的新类

接下来实现createNewClass函数,动态生成新类,让新类的方法自动调用原类实例的方法并省略第一个参数。这里假设原方法的第一个参数需要传入原实例本身(你可以根据实际需求调整第一个参数的传入值):

function createNewClass<T extends object>(originalInstance: T) {
  return class {
    constructor() {
      // 遍历原类原型上的所有方法
      const prototype = Object.getPrototypeOf(originalInstance);
      Object.getOwnPropertyNames(prototype).forEach(methodName => {
        // 跳过构造函数,只处理方法
        if (methodName === 'constructor') return;
        const originalMethod = originalInstance[methodName];
        if (typeof originalMethod === 'function') {
          // 为新类绑定方法:调用原方法时,第一个参数传入原实例,后续参数由新方法接收
          (this as any)[methodName] = (...args: any[]) => {
            return originalMethod.call(originalInstance, originalInstance, ...args);
            // 如果原方法的第一个参数不需要传入原实例,替换成你需要的固定值即可,比如:
            // return originalMethod.call(originalInstance, undefined, ...args);
          };
        }
      });
    }
  } as ClassWithoutFirstParam<T>;
}

使用示例:

// 创建原类实例
const instanceA = new A();

// 生成新类
const ClassB = createNewClass(instanceA);
const instanceB = new ClassB();

// 调用新方法,无需传入第一个参数
instanceB.aCall("test payload"); // 等价于 instanceA.aCall(instanceA, "test payload")
instanceB.bCall(123); // 等价于 instanceA.bCall(instanceA, 123)
instanceB.cCall(); // 等价于 instanceA.cCall(instanceA)

补充说明

  • 如果原类的方法是静态方法,需要调整遍历逻辑(遍历原类本身而不是原型)。
  • 工具类型ClassWithoutFirstParam会自动处理所有方法,包括可选参数、重载方法等TypeScript支持的函数类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:47:15