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

如何用TypeScript装饰器实现类似Lombok的@Getters功能?

解决TypeScript装饰器实现Lombok @Getters的类型报错问题

需求说明

我希望复刻Java Lombok的@Getters功能,预期实现效果如下:

装饰器使用示例

@Getters()
export class Example {
  private property: string;
}

调用示例

const test = new Example();
console.log(test.getProperty()); // 期望无类型报错且正常调用

当前实现代码

我尝试通过TypeScript装饰器重写类定义来实现该功能,代码如下:

import { capitalize } from "lodash";

export const Getters = () => <T extends {new(...args:any[]):{}}>(constructor:T) => {  
  return class extends constructor {
    constructor(...args: any[]) {
      super(...args);
      const props = Reflect.ownKeys(this);
      props.forEach((prop: string) => {
        const capitalizedKey = capitalize(prop);
        const methodName = `get${capitalizedKey}`;
        Reflect.defineProperty(this, methodName, { value: () => this[prop], configurable: false, enumerable: false });
      });
    }
  }
}

遇到的问题

调用test.getProperty()时会触发类型报错:The X property does not exist on the X type.,但通过方括号语法test['getProperty']()可以正常执行。

解决方案

问题核心是TypeScript类型系统无法自动识别装饰器动态添加的方法,需要通过类型编程为类补充getter方法的类型定义:

1. 定义Getter类型映射工具

创建类型转换工具,将类的属性映射为对应的getter方法类型:

type GetterMethods<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
};

2. 修改装饰器的类型与实现

让装饰器返回的类同时继承原类并实现GetterMethods<T>,同时调整类型断言让TypeScript识别动态添加的方法:

import { capitalize } from "lodash";

// 属性转getter方法的类型定义
type GetterMethods<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
};

export const Getters = () => <T extends new (...args: any[]) => {}>(constructor: T) => {
  return class extends constructor implements GetterMethods<InstanceType<T>> {
    constructor(...args: any[]) {
      super(...args);
      const props = Reflect.ownKeys(this);
      props.forEach((prop) => {
        const propStr = prop as string;
        const capitalizedKey = capitalize(propStr);
        const methodName = `get${capitalizedKey}` as keyof GetterMethods<InstanceType<T>>;
        Reflect.defineProperty(this, methodName, {
          value: () => this[propStr],
          configurable: false,
          enumerable: false
        });
      });
    }
  } as T & (new (...args: ConstructorParameters<T>) => GetterMethods<InstanceType<T>>);
};

3. 配置TypeScript编译选项

确保tsconfig.json中开启必要配置:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "strict": true,
    "lib": ["ESNext"]
  }
}

验证效果

修改后,test.getProperty()不仅能正常运行,TypeScript也会正确识别该方法的类型,不再出现类型报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 02:54:23