类验证器:使用类成员作为装饰器参数

问题描述

我有一个注册 DTO,其中一个成员依赖另一个成员。

IsPostalCode 上的 zip 需要知道 countryCode/locale,这是其他类成员之一。

是否可以使用类成员作为装饰器参数?

import {
  IsEmail,IsISO31661Alpha2,IsPostalCode,Isstring
} from "class-validator"

export class SignupDto {
  @IsEmail()
  email: string

  @Isstring()
  password: string

  @IsISO31661Alpha2()
  countryCode: string

  // Something like this
  @IsPostalCode(this.countryCode)
  zip: string
}

解决方法

由于装饰器在打字稿中的工作方式,装饰器不能固有地使用它们内部的类属性。您可以创建一个 custom validation decorator 来读取类的其他属性并正确验证 zip 属性,但这可能需要一些工作才能开始。

所以回答你的问题:

是否可以使用类成员作为装饰器参数?

不,不是。

,

您可以创建一个自定义验证器,如下所示:

import {
  ValidationOptions,registerDecorator,ValidationArguments,buildMessage,} from 'class-validator';
/**
* Install validator package from npm. class-validator uses validator under the 
* hood
*/
import {isISO31661Alpha2,isPostalCode} from 'validator';

export function IsPostalCodeOf(
  property: string,validationOptions?: ValidationOptions,) {
  // eslint-disable-next-line @typescript-eslint/ban-types
  return function(object: Object,propertyName: string) {
    registerDecorator({
      name: 'isPostalCodeOf',target: object.constructor,propertyName: propertyName,constraints: [property],options: validationOptions,validator: {
        validate(value: any,args: ValidationArguments) {
          // Getting the country code field from the argument.
          // countryCode field from SignupDto
          const [countryCodeField] = args.constraints;
          // Getting the value of the countryCode Field
          const countryCode = (args.object as any)[countryCodeField];
          // Checking if the country code is valid even though it is checked 
          // at class level 
          if (!isISO31661Alpha2(countryCode)) {
          // Invalid county code
            return false;
          }
          // Checks if the value (zip) belongs in the extracted countryCode 
          // field
          return isPostalCode(value,countryCode);
        },// Specifiy your error message here.
        defaultMessage: buildMessage(
          eachPrefix =>
            `${eachPrefix} $property must be a valid postal 
             code in the specified country `,validationOptions,),},});
  };
}

用法:

export class SignupDto {
  @IsEmail()
  email: string

  @IsString()
  password: string

  @IsISO31661Alpha2()
  countryCode: string

  @IsPostalCodeOf('countryCode')
  zip: string
}