如何枚举类的装饰器?自定义Injectable实现技术问询
判断类是否应用特定装饰器的实现方案
TypeScript 装饰器本身不会自动留存元数据,要实现检测或枚举装饰器的需求,得借助 reflect-metadata 库配合 Reflect API 手动记录元数据,具体步骤如下:
1. 先配置依赖与基础装饰器改造
首先安装 reflect-metadata 包(npm install reflect-metadata),然后修改装饰器逻辑,给目标类添加唯一标识的元数据:
import "reflect-metadata"; // 用Symbol作为元数据的唯一key,避免命名冲突 const MY_DECORATOR_KEY = Symbol('myDecorator'); function myDecorator(ctor: Function): void { console.log(ctor); // 给类标记已应用该装饰器的元数据 Reflect.defineMetadata(MY_DECORATOR_KEY, true, ctor); } @myDecorator class MyClass { static isInjectable: boolean; public a: number = 5; constructor() { this.a = 5; } }
2. 编写检测特定装饰器的工具函数
通过 Reflect.getMetadata 读取元数据,判断类是否应用了目标装饰器:
function hasTargetDecorator(target: Function, decoratorKey: symbol): boolean { return Reflect.hasMetadata(decoratorKey, target); } // 使用示例 console.log(hasTargetDecorator(MyClass, MY_DECORATOR_KEY)); // 输出 true
3. 实现枚举所有装饰器的逻辑
如果要枚举类上的所有装饰器,需要在每个装饰器里统一维护一个装饰器列表的元数据:
const DECORATORS_COLLECTION_KEY = Symbol('decoratorsCollection'); function myDecorator(ctor: Function): void { // 获取已有的装饰器列表,无则初始化空数组 const decorators = Reflect.getMetadata(DECORATORS_COLLECTION_KEY, ctor) || []; decorators.push('myDecorator'); // 可存储装饰器标识或引用 Reflect.defineMetadata(DECORATORS_COLLECTION_KEY, decorators, ctor); } function anotherDecorator(ctor: Function): void { const decorators = Reflect.getMetadata(DECORATORS_COLLECTION_KEY, ctor) || []; decorators.push('anotherDecorator'); Reflect.defineMetadata(DECORATORS_COLLECTION_KEY, decorators, ctor); } @myDecorator @anotherDecorator class MyClass { // ...类内容 } // 枚举所有应用的装饰器 const allAppliedDecorators = Reflect.getMetadata(DECORATORS_COLLECTION_KEY, MyClass) || []; console.log(allAppliedDecorators); // 输出 ['anotherDecorator', 'myDecorator'](装饰器执行顺序为从下到上)
关键注意点
- 必须引入
reflect-metadata库,TypeScript 原生 Reflect API 的元数据操作依赖该库支持。 - 类装饰器的执行顺序是从下到上(靠近类定义的装饰器先执行),因此元数据列表的顺序会和装饰器书写顺序相反。
- 自定义装饰器时要统一元数据存储规则,才能保证枚举和检测的准确性。
内容的提问来源于stack exchange,提问作者Iceneo
相关产品推荐
相关产品推荐

