TypeScript中如何获取实例上标记了@readTypes装饰器的所有函数
实现方案
你需要在自定义装饰器中额外给被装饰的方法添加唯一的元数据标记,之后遍历实例原型上的所有方法,筛选出带有该标记的即可。
完整可运行代码如下:
import 'reflect-metadata'; // 定义唯一的元数据key,避免命名冲突 const READ_TYPES_DECORATOR_KEY = Symbol('read-types'); function readTypes() { const decorator: MethodDecorator = (target, propertyKey, description) => { // 原有逻辑保留 const args = Reflect.getMetadata( 'design:paramtypes', target, propertyKey ).map(c => c.name); const ret = Reflect.getMetadata('design:returntype', target, propertyKey); console.log(`Arguments type: ${args.join(', ')}.`); console.log(`Return type: ${ret.name}.`); // 新增:给被装饰的方法添加元数据标记 Reflect.defineMetadata(READ_TYPES_DECORATOR_KEY, true, target, propertyKey); }; return decorator; } // 新增:获取实例上所有被@readTypes装饰的方法名 function getReadTypesMethods(instance: any): string[] { const prototype = Object.getPrototypeOf(instance); // 遍历原型上所有可枚举的自身属性 return Object.getOwnPropertyNames(prototype).filter(propertyName => { // 过滤掉构造函数 if (propertyName === 'constructor') return false; // 判断是否是方法且带有指定元数据标记 return typeof prototype[propertyName] === 'function' && Reflect.hasMetadata(READ_TYPES_DECORATOR_KEY, prototype, propertyName); }); } class Foo {} class Bar { @readTypes() public fn(a: number, b: string, c: Foo): boolean { return true; } // 测试未被装饰的方法不会被采集 public otherFn() { return false; } } const barInstance = new Bar(); // 调用方法获取所有标记了@readTypes的方法名 const decoratedMethods = getReadTypesMethods(barInstance); console.log(decoratedMethods); // 输出 ['fn']
补充说明
如果需要支持继承场景,只需要修改getReadTypesMethods函数,递归向上遍历整个原型链筛选即可。
内容的提问来源于stack exchange,提问作者jonlal
相关产品推荐
相关产品推荐

