如何在GraphQL中为@Args参数添加class-validator装饰器
报错原因
@IsUUID() 是class-validator提供的类属性装饰器,只能作用于类(比如DTO类)的属性上,直接修饰Resolver的方法参数会因为装饰器类型不匹配触发签名错误。
以下是两种不需要额外创建DTO的解决方案:
方案1:使用Nest内置ParseUUIDPipe(推荐)
这是最简便的方案,不需要引入class-validator的装饰器,直接利用Nest内置的UUID校验管道实现参数验证。使用前需要从@nestjs/common包导入ParseUUIDPipe,修改代码如下:
@UseGuards(new AuthGuard(['user', 'admin'])) @Mutation(() => ProductEntity) async updateProduct( @User() user, // 直接在@Args中传入ParseUUIDPipe即可完成UUID校验 // 如需指定UUID版本可改用 ParseUUIDPipe.forVersion('4') @Args('productId', ParseUUIDPipe) productId: string, @Args('inputs', {}) inputs: UpdateProductInputDto, ): Promise<ProductEntity> { return this.productService.updateProduct(user.id, productId, inputs); }
如果传入的productId不是合法UUID,会自动返回400错误,不需要额外处理逻辑。
方案2:自定义参数装饰器封装class-validator校验
如果确实需要复用class-validator的@IsUUID校验逻辑,可以自定义一个参数装饰器,手动封装验证逻辑:
首先新建自定义装饰器:
import { createParamDecorator, ExecutionContext, BadRequestException } from '@nestjs/common'; import { validateSync, IsUUID } from 'class-validator'; import { plainToInstance } from 'class-transformer'; export const UUIDArgs = createParamDecorator((data: string, ctx: ExecutionContext) => { const gqlCtx = ctx.getArgByIndex(2); const value = gqlCtx.args[data]; // 临时类封装参数做校验,不需要对外暴露 class TempValidationClass { @IsUUID() value: string; } const instance = plainToInstance(TempValidationClass, { value }); const errors = validateSync(instance); if (errors.length > 0) { throw new BadRequestException(`参数${data}不是合法的UUID`); } return value; });
之后在Resolver中直接使用即可:
@UseGuards(new AuthGuard(['user', 'admin'])) @Mutation(() => ProductEntity) async updateProduct( @User() user, @UUIDArgs('productId') productId: string, @Args('inputs', {}) inputs: UpdateProductInputDto, ): Promise<ProductEntity> { return this.productService.updateProduct(user.id, productId, inputs); }
内容的提问来源于stack exchange,提问作者Roman Karpyshyn
相关产品推荐
相关产品推荐

