如何让NestJS中class-validator的DTO字段同时支持数字与数字字符串验证?
实现方案
当然可以实现,你只需要调整字段类型并搭配合适的验证规则即可,以下是两种可行方案:
方案一:自定义验证装饰器(推荐)
先创建一个支持数字/数字字符串的自定义验证器:
import { registerDecorator, ValidationOptions } from 'class-validator'; export function IsNumberOrNumberString(validationOptions?: ValidationOptions) { return function (target: Object, propertyKey: string) { registerDecorator({ name: 'isNumberOrNumberString', target: target.constructor, propertyName: propertyKey, options: validationOptions, validator: { validate(value: unknown) { if (typeof value === 'number') { return !isNaN(value) && isFinite(value); } if (typeof value === 'string') { return /^\d+(\.\d+)?$/.test(value) && !isNaN(Number(value)); } return false; }, defaultMessage() { return '必须是数字或合法的数字字符串'; }, }, }); }; }
然后修改你的DTO:
import { IsNotEmpty, Expose } from 'class-validator'; import { IsNumberOrNumberString } from './path-to-your-decorator'; export default class CatDto extends BaseDto { @IsNotEmpty() @Expose() name: string; @IsNotEmpty() @IsNumberOrNumberString() @Expose() age: number | string; }
方案二:用@ValidateIf拆分验证规则
不需要自定义装饰器,通过条件验证分别处理两种类型:
import { IsNotEmpty, Expose, IsNumber, IsNumberString, ValidateIf } from 'class-validator'; export default class CatDto extends BaseDto { @IsNotEmpty() @Expose() name: string; @IsNotEmpty() // 仅当值为number类型时,校验是否为合法数字 @ValidateIf((_, value) => typeof value === 'number') @IsNumber() // 仅当值为string类型时,校验是否为合法数字字符串 @ValidateIf((_, value) => typeof value === 'string') @IsNumberString() @Expose() age: number | string; }
可选:自动转换类型
如果希望业务逻辑中统一使用number类型,可以搭配class-transformer的@Transform装饰器,自动将数字字符串转为数字:
import { Transform } from 'class-transformer'; // 在age字段上添加 @Transform(({ value }) => { if (typeof value === 'string' && /^\d+(\.\d+)?$/.test(value)) { return Number(value); } return value; })
内容的提问来源于stack exchange,提问作者kan
相关产品推荐
相关产品推荐

