typestack / class-validator

Decorator-based property validation for classes.
MIT License
10.92k stars 787 forks source link

question: How to invoke class-validator on a class itself #2512

Open yashg32 opened 2 months ago

yashg32 commented 2 months ago

Validators are typically invoked on class variables, not on the class itself. Is it possible to apply a validator to a class? I'm trying to use a decorator as a clean solution that can also be used elsewhere. We want to define certain properties that atleast one of them should exist directly on class?

import {
  registerDecorator,
  ValidationOptions,
  ValidationArguments,
  ValidatorConstraint,
  ValidatorConstraintInterface,
} from 'class-validator';

@ValidatorConstraint({ async: false })
export class AtLeastOneOf implements ValidatorConstraintInterface {
  validate(_, args: ValidationArguments) {
    const properties = args.constraints;
    const value = args.object as any;

    return properties.some(property => value[property] !== undefined && value[property] !== null);
  }

  defaultMessage(args: ValidationArguments) {
    const properties = args.constraints;
    return `At least one of the following properties must be provided: ${properties.join(', ')}.`;
  }
}

export function AtLeastOneField(properties: string[], validationOptions?: ValidationOptions) {
  return function (object: any, propertyName: string) {
    registerDecorator({
      name: 'AtLeastOneField',
      target: object.constructor,
      propertyName,
      options: validationOptions,
      constraints: properties,
      validator: AtLeastOneOf,
    });
  };
}

@AtLeastOneField(['photoId', 'userId']) // not work here
export class ListUsers {
  @IsID()
  @IsOptional()
  userId?: string;

  @IsID()
  @IsOptional()
  accountId?: string;

  @IsID()
  @IsOptional()
  photoId?: string; 

}