class-validator icon indicating copy to clipboard operation
class-validator copied to clipboard

fix: handle symbols in constraintToString method with array

Open adrienboulle opened this issue 2 years ago • 3 comments

Description

When implementing custom validators and using array of symbols as constraints, an error is raised when the error message is generated for a failed validation.

Minimal code-snippet showcasing the problem

const mySymbol = Symbol('mySymbol');

function IsSameType(property: unknown, validationOptions?: ValidationOptions) {
  return function (object: object, propertyName: string): void {
    registerDecorator({
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      constraints: [property],
      validator: {
        validate(value: any, args: ValidationArguments) {
          return args.constraints[0].some(t => typeof value === typeof t);
        },
        defaultMessage: buildMessage(
          eachPrefix + '$property must be of type ' + properties.map(property => typeof property).join(' or '),
          validationOptions
        ),
      },
    });
  };
}

class MyClass {
  @IsOneOfTypes([mySymbol])
  property: symbol;
}

const model = new MyClass();

// this will raise an error when generating the message
validator.validate(model)

https://github.com/typestack/class-validator/pull/2027

Expected behavior No error should be raised when generating a failed validation message.

Actual behavior An error is raised when generating a failed validation message.

adrienboulle avatar Mar 29 '23 23:03 adrienboulle

We have yet to take a look at this issue. Please be patient.

If others are having the same problem, please chime in or use reactions to show that.

braaar avatar Apr 09 '24 06:04 braaar

I can't get your reproduction to run on my end. This is what I have

import {
  ValidationArguments,
  ValidationOptions,
  buildMessage,
  registerDecorator,
} from "class-validator";
import * as validator from "class-validator";

const mySymbol = Symbol("mySymbol");

function IsSameType(property: unknown, validationOptions?: ValidationOptions) {
  return function (object: object, propertyName: string): void {
    registerDecorator({
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      constraints: [property],
      validator: {
        validate(value: any, args: ValidationArguments) {
          return args.constraints[0].some((t) => typeof value === typeof t);
        },
        defaultMessage: buildMessage(
          eachPrefix +
            "$property must be of type " +
            properties.map((property) => typeof property).join(" or "),
          validationOptions
        ),
      },
    });
  };
}

class MyClass {
  @IsOneOfTypes([mySymbol])
  property: symbol;
}

const model = new MyClass();

// this will raise an error when generating the message
validator.validate(model);

IsOneOfTypes appears to not be defined anywhere, and I'm seeing this type error in buildMessage.

Argument of type 'string' is not assignable to parameter of type '(eachPrefix: string, args?: ValidationArguments) => string'.

Could you correct this in your snippet so that I can see this issue for myself?

braaar avatar Apr 17 '24 05:04 braaar