Class-Validator:如何仅在内置验证通过后执行自定义验证且不中断其他验证
实现类验证的条件执行逻辑
现有用于注册请求体的验证类代码如下:
class RegisterBody { @IsEmail() @IsEmailRegistered() email: string; @IsStrongPassword() password: string; }
需要实现以下验证规则:
email字段的@IsEmailRegistered()验证仅在@IsEmail()验证通过后才执行@IsStrongPassword()验证无论其他字段验证结果如何,始终执行- 禁止使用
stopAtFirstError配置
解决方案一:使用@ValidateIf条件验证
通过@ValidateIf装饰器判断邮箱格式是否合法,仅当格式合法时才执行@IsEmailRegistered验证:
import { IsEmail, IsStrongPassword, ValidateIf, isEmail } from 'class-validator'; class RegisterBody { // 先验证邮箱格式 @IsEmail() // 仅当邮箱格式合法时,才执行后续的已注册检查 @ValidateIf((obj) => isEmail(obj.email)) @IsEmailRegistered() email: string; // 默认始终执行,不受其他字段验证结果影响 @IsStrongPassword() password: string; }
解决方案二:在自定义验证器中内置条件判断
如果@IsEmailRegistered是你自定义的验证器,可以直接在验证逻辑里先检查邮箱格式,格式不合法时跳过注册检查:
import { IsEmail, IsStrongPassword, registerDecorator, ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments, isEmail } from 'class-validator'; // 自定义验证器约束 @ValidatorConstraint({ async: true }) class IsEmailRegisteredConstraint implements ValidatorConstraintInterface { async validate(email: string, args: ValidationArguments) { // 先检查邮箱格式,不合法则直接返回true(不触发错误) if (!isEmail(email)) { return true; } // 执行邮箱是否已注册的检查逻辑(示例) const isRegistered = await yourEmailCheckService.isRegistered(email); return !isRegistered; } } // 自定义装饰器 function IsEmailRegistered(validationOptions?: ValidationArguments) { return function (target: Object, propertyName: string) { registerDecorator({ target: target.constructor, propertyName: propertyName, options: validationOptions, validator: IsEmailRegisteredConstraint, }); }; } // 验证类 class RegisterBody { @IsEmail() @IsEmailRegistered() email: string; @IsStrongPassword() password: string; }
两种方案都能满足需求:
- 方案一无需修改自定义验证器,直接通过
@ValidateIf实现条件控制 - 方案二将条件逻辑封装在验证器内部,代码更简洁
内容的提问来源于stack exchange,提问作者Mhmd Al-Rshedy
相关产品推荐
相关产品推荐

