NestJS如何封装第三方装饰器并设置元数据供Reflector校验
问题解答
问题1:是否有方法直接通过Reflector检测控制器方法上的第三方装饰器?
有两种可行方案:
- 查看第三方库源码:直接找到
@Protected()装饰器的实现代码,找到其调用Reflect.defineMetadata()时传入的第一个参数,即为该装饰器使用的元数据key,拿到后就可以通过reflector.get(对应key, context.getHandler())正常获取元数据。 - 枚举元数据key:如果不方便查看源码,可以在Guard中打印当前方法的所有元数据key,找到对应装饰器留下的标记:
const allMetadataKeys = Reflect.getMetadataKeys(context.getHandler()); console.log(allMetadataKeys); // 从输出的key中筛选和Protected/权限相关的字段即可
如果上述两种方法都找不到对应元数据,说明该第三方装饰器没有通过元数据标记,而是直接修改了方法的属性描述符,这种情况无法直接通过Reflector检测,需要走自定义装饰器封装的方案。
问题2:如果必须自行设置元数据,如何正确封装自定义装饰器满足需求?
你遇到的"无法解析方法装饰器签名,void类型无调用签名"报错,是因为你封装的时候没有正确组合装饰器、也没有返回合法的装饰器函数导致的。NestJS官方提供了applyDecorators工具函数,专门用来聚合多个装饰器,你可以按如下方式实现:
首先导入依赖:
import { applyDecorators, SetMetadata } from '@nestjs/common'; import { Protected } from '你的第三方库包名';
实现自定义装饰器:
// 你自己定义的元数据key,后续在Guard中直接用这个key取值即可 export const MY_PROTECTED_KEY = 'my_protected'; export const MyProtected = () => { return applyDecorators( Protected(), // 调用第三方的Protected装饰器 SetMetadata(MY_PROTECTED_KEY, true) // 设置自定义元数据 ); };
在控制器方法上使用自定义装饰器:
@Get() @MyProtected() findAll() { // 你的业务逻辑 }
在Guard中取值:
const isProtected = this.reflector.get(MY_PROTECTED_KEY, context.getHandler()) ?? false;
该方案完全符合TS类型规范,不会再出现签名报错的问题。
内容的提问来源于stack exchange,提问作者user842225
相关产品推荐
相关产品推荐

