如何通过TypeScript装饰器实现类属性赋值时自动转为小写
问题根源
- 代码中
const obj: User = plainObj仅为TypeScript的类型标注,运行时不会创建User类的实例,obj本质仍是普通对象,不会触发装饰器定义的get/set逻辑。 - 原有
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
相关产品推荐
相关产品推荐

