如何获取装饰器所需类原型?TypeScript元数据读取问题
解决TypeScript中动态获取类元数据的问题
问题根源
后端返回的JSON是普通JavaScript对象,并非你定义的InnerClassA、InnerClassB、ABC类的实例,这类对象的原型链指向Object.prototype,而非对应类的原型。直接用Reflect.getPrototypeOf或Object.getPrototypeOf只能拿到Object的原型,自然读不到存在类原型上的元数据。
解决方案
1. 给类绑定类型标识并维护映射表
在每个需要转换的类上添加静态标识,同时维护一个类映射表,方便转换时快速找到对应类:
class InnerClassA { static __type = 'InnerClassA'; @Label('InnerA名称') name: string; // 其他属性 } class ABC { static __type = 'ABC'; @Label('主名称') name: string; @Label('内部A') innerA: InnerClassA; // 其他属性 } // 类型-类映射表 const classMap = { InnerClassA, InnerClassB, ABC };
2. 转换时创建类实例(安全可靠)
在transformObjectToTree中,通过类型标识找到对应类,创建实例并赋值后端数据,此时实例的原型链能正确关联类原型,即可读取元数据:
function transformObjectToTree(obj: any, type: string): TreeNode | LeafNode { const TargetClass = classMap[type]; if (!TargetClass) throw new Error('未知类型'); // 创建类实例并赋值后端数据 const instance = Object.assign(new TargetClass(), obj); // 读取元数据(两种方式都可行) const label = Reflect.getMetadata('label', TargetClass.prototype, 'name'); // 或:Reflect.getMetadata('label', instance, 'name') // 后续树结构转换逻辑 }
3. 改用全局元数据存储(脱离原型依赖)
如果不想依赖原型链,可以修改装饰器,把元数据存在全局映射表中,直接通过类名和属性名获取:
// 全局元数据存储 const propertyMetaStore = new Map<string, Map<string, string>>(); function Label(label: string): PropertyDecorator { return (target, propertyKey) => { const className = target.constructor.name; if (!propertyMetaStore.has(className)) { propertyMetaStore.set(className, new Map()); } propertyMetaStore.get(className)!.set(propertyKey.toString(), label); }; } // 转换时直接从全局存储读取 function transformObjectToTree(obj: any, className: string): TreeNode | LeafNode { const metaMap = propertyMetaStore.get(className); if (!metaMap) throw new Error('无对应元数据'); const label = metaMap.get('name'); // 后续树结构转换逻辑 }
注意事项
- 后端返回的数据最好携带类型标识(比如每个对象包含
__type字段),确保转换时能精准匹配类。 - 使用
Object.assign创建实例时,若类的构造函数有复杂初始化逻辑,需调整赋值逻辑,避免覆盖初始化结果。
内容的提问来源于stack exchange,提问作者Vlad
相关产品推荐
相关产品推荐

