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

如何使用装饰器重命名TypeScript类实例的属性键?

问题描述

我定义了如下类:

class A {
  description: string
}

我希望创建该类的实例时,能够正常使用description来设置属性,但访问实例时,该属性以a.desc的形式存在。

常规实现方式如下:

class A {
  desc: string
  constructor(description: string) {
    this.desc = description
  }
}
const instance = new A("xxx xxx xxx")
console.log(instance) // { desc: "xxx xxx xxx" }
console.log(instance.desc) // "xxx xxx xxx"

我想通过装饰器实现类似效果,比如:

class A {
  @RenameKey("desc")
  description: string
}

我了解过@Expose()装饰器,但它会同时修改输入和输出的属性名,而我需要输入时仍用description,输出时改为desc。

请问是否可以使用装饰器重命名类实例的属性键?我知道可以手动这么做:

const a = new A("xxx xxx xxx")
a.desc = a.description
delete a.description

但希望通过装饰器自动完成这个需求。


解决方案

完全可以通过自定义装饰器实现这个需求,以下提供两种实用方案:

方案一:访问器代理属性(推荐)

通过装饰器在类原型上为description定义getter/setter,将读写操作转发到desc属性,同时保证实例仅存储desc:

function RenameKey(targetKey: string) {
  return function (target: any, propertyKey: string) {
    Object.defineProperty(target, propertyKey, {
      get() {
        return this[targetKey];
      },
      set(value: any) {
        this[targetKey] = value;
      },
      enumerable: false, // 让description不在实例枚举中显示
      configurable: true
    });
  };
}

// 使用装饰器
class A {
  desc!: string;

  @RenameKey("desc")
  description!: string;
}

// 测试
const instance = new A();
instance.description = "测试内容";
console.log(instance.desc); // 输出:测试内容
console.log(instance); // 输出:{ desc: "测试内容" }
console.log(instance.description); // 输出:测试内容

方案二:实例化后自动迁移属性

如果希望实例化后直接移除description,只保留desc,可以通过装饰器重写类的构造函数,自动完成属性迁移:

function RenameKey(targetKey: string) {
  return function (target: any, propertyKey: string) {
    const originalConstructor = target.constructor;

    // 重写构造逻辑
    target.constructor = function (...args: any[]) {
      const instance = new originalConstructor(...args);
      
      // 迁移属性并删除原属性
      if (instance.hasOwnProperty(propertyKey)) {
        instance[targetKey] = instance[propertyKey];
        delete instance[propertyKey];
      }

      return instance;
    };
  };
}

// 使用装饰器
class A {
  @RenameKey("desc")
  description: string;

  constructor(description: string) {
    this.description = description;
  }
}

// 测试
const instance = new A("测试内容");
console.log(instance); // 输出:{ desc: "测试内容" }

方案对比

  • 方案一:保留description作为读写入口,外部仍可通过description操作,但实例实际存储的是desc,适合需要兼容旧代码的场景。
  • 方案二:完全移除原属性,仅保留目标属性,和你手动处理的逻辑完全一致。

内容的提问来源于stack exchange,提问作者Islam Y-

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 21:05:57