yalpsid eman
yalpsid eman

Reputation: 3432

Can I specify the order to execute validation decorators with class-validator?

Let's say one has a class, Post, that one wants to validate.

export class Post {
  @IsArray()
  tags: string[];
}

Let's now say that he wants to ensure that the word 'mistake' never appears in the tags field. He writes a custom validation decorator to do this:

export function NoMistakes (validationOptions?: ValidationOptions) {
  return function (object: Object, propertyName: string) {
    registerDecorator({
      name: 'noMistakes',
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      validator: {
        validate (tags: any, args: ValidationArguments) {
          tags.forEach(tag => {
            if (tag == 'mistake') {
              return false;
            }
          });

          return true;
        }
      }
    });
  }
}

Now, he rewrites Post as so:

export class Post {
  @IsArray()
  @NoMistakes()
  tags: string[];
}

The problem occurs, for example, when tags in not of type int. In this case, an error occurs in the custom validator when trying to iterate over something that is not an array.

How can one have the validator @IsArray be executed before the custom validator? In general, is there a way one can choose the order of the validations?

Upvotes: 10

Views: 6874

Answers (1)

Javien
Javien

Reputation: 188

Typescript decorator order follows: see

  1. The expressions for each decorator are evaluated top-to-bottom.
  2. The results are then called as functions from bottom-to-top.

That means class-validator checks validation decorator bottom-to-top
So, you can edit your Post class like this.

export class Post {
  @NoMistakes() // 2nd
  @IsArray() // 1st
  tags: string[];
}

And you can give stopAtFirstError options to skip @NoMistakes() when @IsArray makes an error.
get more informations about validator options:
https://www.npmjs.com/package/class-validator#passing-options

Upvotes: 14

Related Questions