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

如何通过TypeScript装饰器实现类属性赋值时自动转为小写

问题根源

  1. 代码中const obj: User = plainObj仅为TypeScript的类型标注,运行时不会创建User类的实例,obj本质仍是普通对象,不会触发装饰器定义的get/set逻辑。
  2. 原有lowerCase装饰器的闭包变量value被所有类实例共享,多个实例操作同一属性时会互相覆盖,存在逻辑缺陷。

解决方案

第一步:修正装饰器逻辑

使用唯一Symbol键将属性值存储在实例自身,避免实例间互相干扰,同时设置正确的可枚举、可配置属性。

第二步:构造类实例接收普通对象参数

新增类构造函数接收普通对象,通过Object.assign赋值触发属性setter逻辑,实现自动转小写。

完整可运行代码

// 需要在tsconfig.json中开启 experimentalDecorators: true 配置
function lowerCase(target: any, propertyKey: string) {
  // 生成唯一存储key,避免属性冲突
  const valueStorageKey = Symbol(`_lower_${propertyKey}`);

  Object.defineProperty(target, propertyKey, {
    get() {
      return this[valueStorageKey]?.toLowerCase() ?? undefined;
    },
    set(newVal: string) {
      this[valueStorageKey] = newVal;
    },
    enumerable: true,
    configurable: true
  });
}

class User {
  @lowerCase
  username: string;

  email: string;

  // 构造函数支持传入普通对象初始化属性
  constructor(plainData: Partial<User>) {
    Object.assign(this, plainData);
  }
}

const plainObj = { username: "USERNAME", email: "example@gmail.com" };
// 实际创建User类实例
const obj = new User(plainObj);

console.log(obj.username); // 输出:username
// 动态赋值也会自动转小写
obj.username = "NEW_USERNAME";
console.log(obj.username); // 输出:new_username

如果不想修改类构造函数,也可以用如下方式赋值:

const obj = new User({} as Partial<User>);
Object.assign(obj, plainObj);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 05:57:02