Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

class-validator

typestack11.8mMIT0.14.1TypeScript support: included

Decorator-based property validation for classes.

readme

class-validator

Build Status codecov npm version install size

Allows use of decorator and non-decorator based validation. Internally uses validator.js to perform validation. Class-validator works on both browser and node.js platforms.

Table of Contents

Installation

npm install class-validator --save

Note: Please use at least npm@6 when using class-validator. From npm@6 the dependency tree is flattened, which is required by class-validator to function properly.

Usage

Create your class and put some validation decorators on the properties you want to validate:

import {
  validate,
  validateOrReject,
  Contains,
  IsInt,
  Length,
  IsEmail,
  IsFQDN,
  IsDate,
  Min,
  Max,
} from 'class-validator';

export class Post {
  @Length(10, 20)
  title: string;

  @Contains('hello')
  text: string;

  @IsInt()
  @Min(0)
  @Max(10)
  rating: number;

  @IsEmail()
  email: string;

  @IsFQDN()
  site: string;

  @IsDate()
  createDate: Date;
}

let post = new Post();
post.title = 'Hello'; // should not pass
post.text = 'this is a great post about hell world'; // should not pass
post.rating = 11; // should not pass
post.email = 'google.com'; // should not pass
post.site = 'googlecom'; // should not pass

validate(post).then(errors => {
  // errors is an array of validation errors
  if (errors.length > 0) {
    console.log('validation failed. errors: ', errors);
  } else {
    console.log('validation succeed');
  }
});

validateOrReject(post).catch(errors => {
  console.log('Promise rejected (validation failed). Errors: ', errors);
});
// or
async function validateOrRejectExample(input) {
  try {
    await validateOrReject(input);
  } catch (errors) {
    console.log('Caught promise rejection (validation failed). Errors: ', errors);
  }
}

Passing options

The validate function optionally expects a ValidatorOptions object as a second parameter:

export interface ValidatorOptions {
  skipMissingProperties?: boolean;
  whitelist?: boolean;
  forbidNonWhitelisted?: boolean;
  groups?: string[];
  dismissDefaultMessages?: boolean;
  validationError?: {
    target?: boolean;
    value?: boolean;
  };

  forbidUnknownValues?: boolean;
  stopAtFirstError?: boolean;
}

IMPORTANT The forbidUnknownValues value is set to true by default and it is highly advised to keep the default. Setting it to false will result unknown objects passing the validation!

Validation errors

The validate method returns an array of ValidationError objects. Each ValidationError is:

{
    target: Object; // Object that was validated.
    property: string; // Object's property that haven't pass validation.
    value: any; // Value that haven't pass a validation.
    constraints?: { // Constraints that failed validation with error messages.
        [type: string]: string;
    };
    children?: ValidationError[]; // Contains all nested validation errors of the property
}

In our case, when we validated a Post object, we have such an array of ValidationError objects:

[{
    target: /* post object */,
    property: "title",
    value: "Hello",
    constraints: {
        length: "$property must be longer than or equal to 10 characters"
    }
}, {
    target: /* post object */,
    property: "text",
    value: "this is a great post about hell world",
    constraints: {
        contains: "text must contain a hello string"
    }
},
// and other errors
]

If you don't want a target to be exposed in validation errors, there is a special option when you use validator:

validator.validate(post, { validationError: { target: false } });

This is especially useful when you send errors back over http, and you most probably don't want to expose the whole target object.

Validation messages

You can specify validation message in the decorator options and that message will be returned in the ValidationError returned by the validate method (in the case that validation for this field fails).

import { MinLength, MaxLength } from 'class-validator';

export class Post {
  @MinLength(10, {
    message: 'Title is too short',
  })
  @MaxLength(50, {
    message: 'Title is too long',
  })
  title: string;
}

There are few special tokens you can use in your messages:

  • $value - the value that is being validated
  • $property - name of the object's property being validated
  • $target - name of the object's class being validated
  • $constraint1, $constraint2, ... $constraintN - constraints defined by specific validation type

Example of usage:

import { MinLength, MaxLength } from 'class-validator';

export class Post {
  @MinLength(10, {
    // here, $constraint1 will be replaced with "10", and $value with actual supplied value
    message: 'Title is too short. Minimal length is $constraint1 characters, but actual is $value',
  })
  @MaxLength(50, {
    // here, $constraint1 will be replaced with "50", and $value with actual supplied value
    message: 'Title is too long. Maximal length is $constraint1 characters, but actual is $value',
  })
  title: string;
}

Also you can provide a function, that returns a message. This allows you to create more granular messages:

import { MinLength, MaxLength, ValidationArguments } from 'class-validator';

export class Post {
  @MinLength(10, {
    message: (args: ValidationArguments) => {
      if (args.value.length === 1) {
        return 'Too short, minimum length is 1 character';
      } else {
        return 'Too short, minimum length is ' + args.constraints[0] + ' characters';
      }
    },
  })
  title: string;
}

Message function accepts ValidationArguments which contains the following information:

  • value - the value that is being validated
  • constraints - array of constraints defined by specific validation type
  • targetName - name of the object's class being validated
  • object - object that is being validated
  • property - name of the object's property being validated

Validating arrays

If your field is an array and you want to perform validation of each item in the array you must specify a special each: true decorator option:

import { MinLength, MaxLength } from 'class-validator';

export class Post {
  @MaxLength(20, {
    each: true,
  })
  tags: string[];
}

This will validate each item in post.tags array.

Validating sets

If your field is a set and you want to perform validation of each item in the set you must specify a special each: true decorator option:

import { MinLength, MaxLength } from 'class-validator';

export class Post {
  @MaxLength(20, {
    each: true,
  })
  tags: Set<string>;
}

This will validate each item in post.tags set.

Validating maps

If your field is a map and you want to perform validation of each item in the map you must specify a special each: true decorator option:

import { MinLength, MaxLength } from 'class-validator';

export class Post {
  @MaxLength(20, {
    each: true,
  })
  tags: Map<string, string>;
}

This will validate each item in post.tags map.

Validating nested objects

If your object contains nested objects and you want the validator to perform their validation too, then you need to use the @ValidateNested() decorator:

import { ValidateNested } from 'class-validator';

export class Post {
  @ValidateNested()
  user: User;
}

Please note that nested object must be an instance of a class, otherwise @ValidateNested won't know what class is target of validation. Check also Validating plain objects.

It also works with multi-dimensional array, like :

import { ValidateNested } from 'class-validator';

export class Plan2D {
  @ValidateNested()
  matrix: Point[][];
}

Validating promises

If your object contains property with Promise-returned value that should be validated, then you need to use the @ValidatePromise() decorator:

import { ValidatePromise, Min } from 'class-validator';

export class Post {
  @Min(0)
  @ValidatePromise()
  userId: Promise<number>;
}

It also works great with @ValidateNested decorator:

import { ValidateNested, ValidatePromise } from 'class-validator';

export class Post {
  @ValidateNested()
  @ValidatePromise()
  user: Promise<User>;
}

Inheriting Validation decorators

When you define a subclass which extends from another one, the subclass will automatically inherit the parent's decorators. If a property is redefined in the descendant, class decorators will be applied on it from both its own class and the base class.

import { validate } from 'class-validator';

class BaseContent {
  @IsEmail()
  email: string;

  @IsString()
  password: string;
}

class User extends BaseContent {
  @MinLength(10)
  @MaxLength(20)
  name: string;

  @Contains('hello')
  welcome: string;

  @MinLength(20)
  password: string;
}

let user = new User();

user.email = 'invalid email'; // inherited property
user.password = 'too short'; // password wil be validated not only against IsString, but against MinLength as well
user.name = 'not valid';
user.welcome = 'helo';

validate(user).then(errors => {
  // ...
}); // it will return errors for email, password, name and welcome properties

Conditional validation

The conditional validation decorator (@ValidateIf) can be used to ignore the validators on a property when the provided condition function returns false. The condition function takes the object being validated and must return a boolean.

import { ValidateIf, IsNotEmpty } from 'class-validator';

export class Post {
  otherProperty: string;

  @ValidateIf(o => o.otherProperty === 'value')
  @IsNotEmpty()
  example: string;
}

In the example above, the validation rules applied to example won't be run unless the object's otherProperty is "value".

Note that when the condition is false all validation decorators are ignored, including isDefined.

Whitelisting

Even if your object is an instance of a validation class it can contain additional properties that are not defined. If you do not want to have such properties on your object, pass special flag to validate method:

import { validate } from 'class-validator';
// ...
validate(post, { whitelist: true });

This will strip all properties that don't have any decorators. If no other decorator is suitable for your property, you can use @Allow decorator:

import {validate, Allow, Min} from "class-validator";

export class Post {

    @Allow()
    title: string;

    @Min(0)
    views: number;

    nonWhitelistedProperty: number;
}

let post = new Post();
post.title = 'Hello world!';
post.views = 420;

post.nonWhitelistedProperty = 69;
(post as any).anotherNonWhitelistedProperty = "something";

validate(post).then(errors => {
  // post.nonWhitelistedProperty is not defined
  // (post as any).anotherNonWhitelistedProperty is not defined
  ...
});

If you would rather to have an error thrown when any non-whitelisted properties are present, pass another flag to validate method:

import { validate } from 'class-validator';
// ...
validate(post, { whitelist: true, forbidNonWhitelisted: true });

Passing context to decorators

It's possible to pass a custom object to decorators which will be accessible on the ValidationError instance of the property if validation failed.

import { validate } from 'class-validator';

class MyClass {
  @MinLength(32, {
    message: 'EIC code must be at least 32 characters',
    context: {
      errorCode: 1003,
      developerNote: 'The validated string must contain 32 or more characters.',
    },
  })
  eicCode: string;
}

const model = new MyClass();

validate(model).then(errors => {
  //errors[0].contexts['minLength'].errorCode === 1003
});

Skipping missing properties

Sometimes you may want to skip validation of the properties that do not exist in the validating object. This is usually desirable when you want to update some parts of the object, and want to validate only updated parts, but skip everything else, e.g. skip missing properties. In such situations you will need to pass a special flag to validate method:

import { validate } from 'class-validator';
// ...
validate(post, { skipMissingProperties: true });

When skipping missing properties, sometimes you want not to skip all missing properties, some of them maybe required for you, even if skipMissingProperties is set to true. For such cases you should use @IsDefined() decorator. @IsDefined() is the only decorator that ignores skipMissingProperties option.

Validation groups

In different situations you may want to use different validation schemas of the same object. In such cases you can use validation groups.

IMPORTANT Calling a validation with a group combination that would not result in a validation (eg: non existent group name) will result in a unknown value error. When validating with groups the provided group combination should match at least one decorator.

import { validate, Min, Length } from 'class-validator';

export class User {
  @Min(12, {
    groups: ['registration'],
  })
  age: number;

  @Length(2, 20, {
    groups: ['registration', 'admin'],
  })
  name: string;
}

let user = new User();
user.age = 10;
user.name = 'Alex';

validate(user, {
  groups: ['registration'],
}); // this will not pass validation

validate(user, {
  groups: ['admin'],
}); // this will pass validation

validate(user, {
  groups: ['registration', 'admin'],
}); // this will not pass validation

validate(user, {
  groups: undefined, // the default
}); // this will not pass validation since all properties get validated regardless of their groups

validate(user, {
  groups: [],
}); // this will not pass validation, (equivalent to 'groups: undefined', see above)

There is also a special flag always: true in validation options that you can use. This flag says that this validation must be applied always no matter which group is used.

Custom validation classes

If you have custom validation logic you can create a Constraint class:

  1. First create a file, lets say CustomTextLength.ts, and define a new class:

    import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from 'class-validator';
    
    @ValidatorConstraint({ name: 'customText', async: false })
    export class CustomTextLength implements ValidatorConstraintInterface {
      validate(text: string, args: ValidationArguments) {
        return text.length > 1 && text.length < 10; // for async validations you must return a Promise<boolean> here
      }
    
      defaultMessage(args: ValidationArguments) {
        // here you can provide default error message if validation failed
        return 'Text ($value) is too short or too long!';
      }
    }

    We marked our class with @ValidatorConstraint decorator. You can also supply a validation constraint name - this name will be used as "error type" in ValidationError. If you will not supply a constraint name - it will be auto-generated.

    Our class must implement ValidatorConstraintInterface interface and its validate method, which defines validation logic. If validation succeeds, method returns true, otherwise false. Custom validator can be asynchronous, if you want to perform validation after some asynchronous operations, simply return a promise with boolean inside in validate method.

    Also we defined optional method defaultMessage which defines a default error message, in the case that the decorator's implementation doesn't set an error message.

  2. Then you can use your new validation constraint in your class:

    import { Validate } from 'class-validator';
    import { CustomTextLength } from './CustomTextLength';
    
    export class Post {
      @Validate(CustomTextLength, {
        message: 'Title is too short or long!',
      })
      title: string;
    }

    Here we set our newly created CustomTextLength validation constraint for Post.title.

  3. And use validator as usual:

    import { validate } from 'class-validator';
    
    validate(post).then(errors => {
      // ...
    });

You can also pass constraints to your validator, like this:

import { Validate } from 'class-validator';
import { CustomTextLength } from './CustomTextLength';

export class Post {
  @Validate(CustomTextLength, [3, 20], {
    message: 'Wrong post title',
  })
  title: string;
}

And use them from validationArguments object:

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

@ValidatorConstraint()
export class CustomTextLength implements ValidatorConstraintInterface {
  validate(text: string, validationArguments: ValidationArguments) {
    return text.length > validationArguments.constraints[0] && text.length < validationArguments.constraints[1];
  }
}

Custom validation decorators

You can also create a custom decorators. Its the most elegant way of using a custom validations. Lets create a decorator called @IsLongerThan:

  1. Create a decorator itself:

    import { registerDecorator, ValidationOptions, ValidationArguments } from 'class-validator';
    
    export function IsLongerThan(property: string, validationOptions?: ValidationOptions) {
      return function (object: Object, propertyName: string) {
        registerDecorator({
          name: 'isLongerThan',
          target: object.constructor,
          propertyName: propertyName,
          constraints: [property],
          options: validationOptions,
          validator: {
            validate(value: any, args: ValidationArguments) {
              const [relatedPropertyName] = args.constraints;
              const relatedValue = (args.object as any)[relatedPropertyName];
              return typeof value === 'string' && typeof relatedValue === 'string' && value.length > relatedValue.length; // you can return a Promise<boolean> here as well, if you want to make async validation
            },
          },
        });
      };
    }
  2. Put it to use:

    import { IsLongerThan } from './IsLongerThan';
    
    export class Post {
      title: string;
    
      @IsLongerThan('title', {
        /* you can also use additional validation options, like "groups" in your custom validation decorators. "each" is not supported */
        message: 'Text must be longer than the title',
      })
      text: string;
    }

In your custom decorators you can also use ValidationConstraint. Lets create another custom validation decorator called IsUserAlreadyExist:

  1. Create a ValidationConstraint and decorator:

    import {
      registerDecorator,
      ValidationOptions,
      ValidatorConstraint,
      ValidatorConstraintInterface,
      ValidationArguments,
    } from 'class-validator';
    
    @ValidatorConstraint({ async: true })
    export class IsUserAlreadyExistConstraint implements ValidatorConstraintInterface {
      validate(userName: any, args: ValidationArguments) {
        return UserRepository.findOneByName(userName).then(user => {
          if (user) return false;
          return true;
        });
      }
    }
    
    export function IsUserAlreadyExist(validationOptions?: ValidationOptions) {
      return function (object: Object, propertyName: string) {
        registerDecorator({
          target: object.constructor,
          propertyName: propertyName,
          options: validationOptions,
          constraints: [],
          validator: IsUserAlreadyExistConstraint,
        });
      };
    }

    note that we marked our constraint that it will by async by adding { async: true } in validation options.

  2. And put it to use:

    import { IsUserAlreadyExist } from './IsUserAlreadyExist';
    
    export class User {
      @IsUserAlreadyExist({
        message: 'User $value already exists. Choose another name.',
      })
      name: string;
    }

Using service container

Validator supports service container in the case if want to inject dependencies into your custom validator constraint classes. Here is example how to integrate it with typedi:

import { Container } from 'typedi';
import { useContainer, Validator } from 'class-validator';

// do this somewhere in the global application level:
useContainer(Container);
let validator = Container.get(Validator);

// now everywhere you can inject Validator class which will go from the container
// also you can inject classes using constructor injection into your custom ValidatorConstraint-s

Synchronous validation

If you want to perform a simple non async validation you can use validateSync method instead of regular validate method. It has the same arguments as validate method. But note, this method ignores all async validations you have.

Manual validation

There are several method exist in the Validator that allows to perform non-decorator based validation:

import { isEmpty, isBoolean } from 'class-validator';

isEmpty(value);
isBoolean(value);

Validation decorators

Decorator Description
Common validation decorators
@IsDefined(value: any) Checks if value is defined (!== undefined, !== null). This is the only decorator that ignores skipMissingProperties option.
@IsOptional() Checks if given value is empty (=== null, === undefined) and if so, ignores all the validators on the property.
@Equals(comparison: any) Checks if value equals ("===") comparison.
@NotEquals(comparison: any) Checks if value not equal ("!==") comparison.
@IsEmpty() Checks if given value is empty (=== '', === null, === undefined).
@IsNotEmpty() Checks if given value is not empty (!== '', !== null, !== undefined).
@IsIn(values: any[]) Checks if value is in an array of allowed values.
@IsNotIn(values: any[]) Checks if value is not in an array of disallowed values.
Type validation decorators
@IsBoolean() Checks if a value is a boolean.
@IsDate() Checks if the value is a date.
@IsString() Checks if the value is a string.
@IsNumber(options: IsNumberOptions) Checks if the value is a number.
@IsInt() Checks if the value is an integer number.
@IsArray() Checks if the value is an array
@IsEnum(entity: object) Checks if the value is a valid enum
Number validation decorators
@IsDivisibleBy(num: number) Checks if the value is a number that's divisible by another.
@IsPositive() Checks if the value is a positive number greater than zero.
@IsNegative() Checks if the value is a negative number smaller than zero.
@Min(min: number) Checks if the given number is greater than or equal to given number.
@Max(max: number) Checks if the given number is less than or equal to given number.
Date validation decorators
@MinDate(date: Date | (() => Date)) Checks if the value is a date that's after the specified date.
@MaxDate(date: Date | (() => Date)) Checks if the value is a date that's before the specified date.
String-type validation decorators
@IsBooleanString() Checks if a string is a boolean (e.g. is "true" or "false" or "1", "0").
@IsDateString() Alias for @IsISO8601().
@IsNumberString(options?: IsNumericOptions) Checks if a string is a number.
String validation decorators
@Contains(seed: string) Checks if the string contains the seed.
@NotContains(seed: string) Checks if the string not contains the seed.
@IsAlpha() Checks if the string contains only letters (a-zA-Z).
@IsAlphanumeric() Checks if the string contains only letters and numbers.
@IsDecimal(options?: IsDecimalOptions) Checks if the string is a valid decimal value. Default IsDecimalOptions are force_decimal=False, decimal_digits: '1,', locale: 'en-US'
@IsAscii() Checks if the string contains ASCII chars only.
@IsBase32() Checks if a string is base32 encoded.
@IsBase58() Checks if a string is base58 encoded.
@IsBase64(options?: IsBase64Options) Checks if a string is base64 encoded.
@IsIBAN() Checks if a string is a IBAN (International Bank Account Number).
@IsBIC() Checks if a string is a BIC (Bank Identification Code) or SWIFT code.
@IsByteLength(min: number, max?: number) Checks if the string's length (in bytes) falls in a range.
@IsCreditCard() Checks if the string is a credit card.
@IsCurrency(options?: IsCurrencyOptions) Checks if the string is a valid currency amount.
@IsISO4217CurrencyCode() Checks if the string is an ISO 4217 currency code.
@IsEthereumAddress() Checks if the string is an Ethereum address using basic regex. Does not validate address checksums.
@IsBtcAddress() Checks if the string is a valid BTC address.
@IsDataURI() Checks if the string is a data uri format.
@IsEmail(options?: IsEmailOptions) Checks if the string is an email.
@IsFQDN(options?: IsFQDNOptions) Checks if the string is a fully qualified domain name (e.g. domain.com).
@IsFullWidth() Checks if the string contains any full-width chars.
@IsHalfWidth() Checks if the string contains any half-width chars.
@IsVariableWidth() Checks if the string contains a mixture of full and half-width chars.
@IsHexColor() Checks if the string is a hexadecimal color.
@IsHSL() Checks if the string is an HSL color based on CSS Colors Level 4 specification.
@IsRgbColor(options?: IsRgbOptions) Checks if the string is a rgb or rgba color.
@IsIdentityCard(locale?: string) Checks if the string is a valid identity card code.
@IsPassportNumber(countryCode?: string) Checks if the string is a valid passport number relative to a specific country code.
@IsPostalCode(locale?: string) Checks if the string is a postal code.
@IsHexadecimal() Checks if the string is a hexadecimal number.
@IsOctal() Checks if the string is a octal number.
@IsMACAddress(options?: IsMACAddressOptions) Checks if the string is a MAC Address.
@IsIP(version?: "4"|"6") Checks if the string is an IP (version 4 or 6).
@IsPort() Checks if the string is a valid port number.
@IsISBN(version?: "10"|"13") Checks if the string is an ISBN (version 10 or 13).
@IsEAN() Checks if the string is an if the string is an EAN (European Article Number).
@IsISIN() Checks if the string is an ISIN (stock/security identifier).
@IsISO8601(options?: IsISO8601Options) Checks if the string is a valid ISO 8601 date format. Use the option strict = true for additional checks for a valid date.
@IsJSON() Checks if the string is valid JSON.
@IsJWT() Checks if the string is valid JWT.
@IsObject() Checks if the object is valid Object (null, functions, arrays will return false).
@IsNotEmptyObject() Checks if the object is not empty.
@IsLowercase() Checks if the string is lowercase.
@IsLatLong() Checks if the string is a valid latitude-longitude coordinate in the format lat, long.
@IsLatitude() Checks if the string or number is a valid latitude coordinate.
@IsLongitude() Checks if the string or number is a valid longitude coordinate.
@IsMobilePhone(locale: string) Checks if the string is a mobile phone number.
@IsISO31661Alpha2() Checks if the string is a valid ISO 3166-1 alpha-2 officially assigned country code.
@IsISO31661Alpha3() Checks if the string is a valid ISO 3166-1 alpha-3 officially assigned country code.
@IsLocale() Checks if the string is a locale.
@IsPhoneNumber(region: string) Checks if the string is a valid phone number using libphonenumber-js.
@IsMongoId() Checks if the string is a valid hex-encoded representation of a MongoDB ObjectId.
@IsMultibyte() Checks if the string contains one or more multibyte chars.
@IsNumberString(options?: IsNumericOptions) Checks if the string is numeric.
@IsSurrogatePair() Checks if the string contains any surrogate pairs chars.
@IsTaxId() Checks if the string is a valid tax ID. Default locale is en-US.
@IsUrl(options?: IsURLOptions) Checks if the string is a URL.
@IsMagnetURI() Checks if the string is a magnet uri format.
@IsUUID(version?: UUIDVersion) Checks if the string is a UUID (version 3, 4, 5 or all ).
@IsFirebasePushId() Checks if the string is a Firebase Push ID
@IsUppercase() Checks if the string is uppercase.
@Length(min: number, max?: number) Checks if the string's length falls in a range.
@MinLength(min: number) Checks if the string's length is not less than given number.
@MaxLength(max: number) Checks if the string's length is not more than given number.
@Matches(pattern: RegExp, modifiers?: string) Checks if string matches the pattern. Either matches('foo', /foo/i) or matches('foo', 'foo', 'i').
@IsMilitaryTime() Checks if the string is a valid representation of military time in the format HH:MM.
@IsTimeZone() Checks if the string represents a valid IANA time-zone.
@IsHash(algorithm: string) Checks if the string is a hash The following types are supported:md4, md5, sha1, sha256, sha384, sha512, ripemd128, ripemd160, tiger128, tiger160, tiger192, crc32, crc32b.
@IsMimeType() Checks if the string matches to a valid MIME type format
@IsSemVer() Checks if the string is a Semantic Versioning Specification (SemVer).
@IsISSN(options?: IsISSNOptions) Checks if the string is a ISSN.
@IsISRC() Checks if the string is a ISRC.
@IsRFC3339() Checks if the string is a valid RFC 3339 date.
@IsStrongPassword(options?: IsStrongPasswordOptions) Checks if the string is a strong password.
Array validation decorators
@ArrayContains(values: any[]) Checks if array contains all values from the given array of values.
@ArrayNotContains(values: any[]) Checks if array does not contain any of the given values.
@ArrayNotEmpty() Checks if given array is not empty.
@ArrayMinSize(min: number) Checks if the array's length is greater than or equal to the specified number.
@ArrayMaxSize(max: number) Checks if the array's length is less or equal to the specified number.
@ArrayUnique(identifier?: (o) => any) Checks if all array's values are unique. Comparison for objects is reference-based. Optional function can be speciefied which return value will be used for the comparsion.
Object validation decorators
@IsInstance(value: any) Checks if the property is an instance of the passed value.
Other decorators
@Allow() Prevent stripping off the property when no other constraint is specified for it.

Defining validation schema without decorators

Schema-based validation without decorators is no longer supported by class-validator. This feature was broken in version 0.12 and it will not be fixed. If you are interested in schema-based validation, you can find several such frameworks in the zod readme's comparison section.

Validating plain objects

Due to nature of the decorators, the validated object has to be instantiated using new Class() syntax. If you have your class defined using class-validator decorators and you want to validate plain JS object (literal object or returned by JSON.parse), you need to transform it to the class instance via using class-transformer).

Samples

Take a look on samples in ./sample for more examples of usages.

Extensions

There are several extensions that simplify class-validator integration with other modules or add additional validations:

Release notes

See information about breaking changes and release notes here.

Contributing

For information about how to contribute to this project, see TypeStack's general contribution guide.

changelog

Changelog

This changelog follows the keep a changelog format to maintain a human readable changelog.

0.14.0 (2022-12-09)

Added

  • add @IsTimeZone decorator to check if given string is valid IANA time zone
  • add @IsISO4217CurrencyCode decorator to check if the string is an ISO 4217 currency code
  • add @IsStrongPassword decorator to check if given password matches specific complexity criteria
  • add @IsBase58 decorator to check if a string is base58 encoded
  • add @IsTaxId decorator to check if a given string is a valid tax ID in a given locale
  • add support for passing function as date generator in @MinDate and @MaxDate decorators
  • add option to print constraint error message instead of constraint type in validation error
  • improve decorator metadata lookup performance
  • return possible values in error message for @IsEnum decorator

Fixed

  • re-added @types/validator as dependency
  • fix error generation when using @NestedValidation
  • pass validation options correctly to validator in @IsDateString decorator
  • support passing Symbol as parameter in error message generation
  • specify supported locales for @IsAlphanumeric decorator
  • correctly assign decorator name in metadata instead of loosing it
  • fix various spelling errors in documentation
  • fix various spelling errors and inconsistencies in JSDoc for decorators

Changed

  • enable forbidUnknownValues option by default
  • remove documentation about deprecated schema based validation and added warning
  • update warning message logged about missing decorator metadata
  • update libphonenumber-js to ^1.10.14 from ^1.9.43
  • update various dev-dependencies

BREAKING CHANGES

forbidUnknownValues option is enabled by default

From this release the forbidUnknownValues is enabled by default. This is the desired behavior for majority of use-cases, but this change may break validation for some. The two scenarios that results in failed validation:

  • when attempting to validate a class instance without metadata for it
  • when using group validation and the specified validation group results in zero validation applied

The old behavior can be restored via specifying forbidUnknownValues: false option when calling the validate functions.

For more details see PR #1798 and #1422 (comment).

@NestedValidation decorator correctly assigns validation errors

Until now the errors from a nested validation in some cases were incorrectly assigned to the parent instead of the child being validated. Now the validation errors are correctly assigned.

For more details see #679.

0.13.2 (2021-11-20)

NOTE: This version fixes a security vulnerability allowing denial of service attacks with a specially crafted request payload. Please update as soon as possible.

Fixed

  • switched to use Array.isArray in array checks from instanceof operator

Changed

  • libphonenumber-js package updated to 1.9.43 from 1.9.7
  • validator package updated to 13.5.2 from 13.5.2
  • various dev-dependencies updated

0.13.1 (2021-01-14)

Added

  • optional mather function has been added to the ArrayUnique decorator

Fixed

  • a typo was fixed in the error message generated by the IsUUID decorator
  • calling ValidationError.toString() doesn't result in an error when forbidNonWhitelisted parameter was used
  • fixed typo in error message generated by IsIn decorator
  • the @types/validator package is correctly installed
  • inlineSources option is enabled in tsconfig preventing various sourcemap errors when consuming the package

Changed

  • various dev dependencies has been updated

0.13.0 (2021-01-11)

Added

  • project is restructured to allow three-shaking
  • added option to fail on first validation error (#620)
  • two new validator option is added:
    • always - allows setting global default for always option for decorators
    • strictGroups - ignore decorators with at least one group, when ValidatorOptions.groups is empty

Fixed

  • the 'any' locale is allowed in the isPostalCode decorator (#634)
  • the IsDateString() decorator now aliases the IsISO8601() decorator (#672)

Changed

  • project tooling has been updated significantly
  • google-libphonenumber has been replaced with libphonenumber-js (this should have no effect on validation)
  • build process generates include both ES/CommonJS and UMD variations
  • various dev dependencies has been updated

0.12.2 (2020-04-23)

Fixed

  • move tslib from peerDependencies to dependencies (827eff1), closes #588

0.12.1 (2020-04-18)

Fixed

  • apply only nested validator for ValidateNested multi-dimensional array (c463be5)

0.12.0 (2020-04-18)

Fixed

  • accept negative timezone in isDateString (#564) (2012d72), closes #565
  • apply all decorators type PropertyDecorator (#556) (5fb36e3), closes #555
  • avoiding metadataStorage from DI (#335) (b57fef4), closes #328 #261 #132
  • correct registerDecorator options argument (7909ec6), closes #302
  • IsNumberString accept isNumbericOptions as argument (62b993f), closes #518 #463
  • optional constraints property in ValidationError (#465) (84680ad), closes #309
  • pass context to ValidationError for async validations (#533) (4eb1216)
  • switch isLatitude & isLongitude validators (#513) (5497179), closes #502
  • switch isLatitude & isLongitude validators (#537) (c27500b)
  • ValidateNested support multi-dimensional arrays (#539) (62678e1)

Changed

Added

  • sync validatorjs version from v10.11.3 to v13.0.0 (09120b7), closes #576 #425

BREAKING CHANGES

  • Validatorjs releases contain some breaking changes e.g. IsMobileNumber or IsHexColor. Please check validatorjs CHANGELOG
  • Validation functions was removed from Validator class to enable tree shaking.

    BEFORE:

    import { Validator } from 'class-validator';
    
    const validator = new Validator();
    validator.isNotIn(value, possibleValues);
    validator.isBoolean(value);

    AFTER:

    import { isNotIn, isBoolean } from 'class-validator';
    
    isNotIn(value, possibleValues);
    isBoolean(value);
  • IsNumberString decorator arguments changed to @IsNumberString(ValidatorJS.IsNumericOptions, ValidationOptions).

0.11.1 (2020-03-18)

Fixed

  • IsNumber validator now works when maxDecimalPlaces=0 (#524) (b8aa922)

Added

0.11.0 (2019-11-01)

Fixed

  • create instance of ValidationError for whitelist errors (#434) (a98f5dd), closes #325
  • pass context for isDefined and custom validators (#296) (0ef898e), closes #292

Added

BREAKING CHANGES

  • update @types/validator from 11.1.0 to version 12.0.0 - please check it's changelog

0.10.2 (2019-10-14)

Fixed

  • apply custom constraint class validation to each item in the array (#295) (5bb704e), closes #260

Added

  • add isLatLong, isLatitude, isLongtitude validators (#427) (3fd15c4), closes #415
  • add IsObject and IsNotEmptyObject new decorators (#334) (0a41aeb)
  • support ES6 Map and Set for regular validators with each option (#430) (a055bba), closes #428

0.10.1 (2019-09-25)

Fixed

  • add default message for isMilitaryTime validator (#411) (204b7df), closes #287
  • add default message for isPort validator (#404) (74e568c)
  • add locale parameter for isAlpha and isAlphanumeric validat… (#406) (2f4bf4e)

Added

  • add skipUndefinedProperties, skipNullProperties options (#414) (76c948a), closes #308

0.10.0 (2019-08-10)

Fixed

  • add correct signature for custom error message handler (249c41d)

Added

  • add IsISO31661Alpha3 and IsISO31661Alpha2 validators (#273) (55c57b3)
  • IsDecimal: implement IsDecimal from validatorjs (#359) (b4c8e21)
  • add isPort decorator (#282) (36684ec)
  • allow validate Map/Set (#365) (f6fcdc5)
  • new ValidatePromise decorator - resolve promise before validate (#369) (35ec04d)
  • replace instanceof Promise and support Promise/A+ (#310) (59eac09)
  • isNumberString now accept validator.js IsNumericOptions as second parameter (#262)

BREAKING CHANGES

  • update @types/validator from 10.4.0 to version 10.11.2 - please check it's changelog (cb960dd)
  • isDateString now check to match only entire ISO Date (#275) (5012464)
  • remove IsCurrencyOptions, IsURLOptions, IsEmailOptions, IsFQDNOptions interfaces and replace with interfaces from @types/validator

0.9.1

Added

  • added option to pass custom context for the decorators

Fixed

  • validating against a schema will validate against that one instead of every registered one

0.9.0 [BREAKING CHANGE]

Added

  • updated validator.js from 9.2.0 to 10.4.0 (Check it's changelog for what has changed.)
    • until now fractional numbers was not allowed in the IsNumberString decorator, now they are allowed
    • until now Gmail addresses could contain multiple dots or random text after a + symbol, this is not allowed anymore
  • IsPhoneNumber decorator has been added which uses the google-libphonenumber library to validate international phone numbers accurately

Fixed

  • update IsURLOptions to match underlying validator host list options
  • added a console warning when no metadata decorator is found as it's possibly not intended
  • the Min and Max decorator will corectly show an inclusive error message when failing
  • fixed a runtime error when validationArguments.value is not a string

0.8.5

Fixed

  • remove ansicolor package, because it's incompatible with IE

0.8.4

Added

  • ValidatorOptions now has a forbidUnknownValues key to prevent unknown objects to pass validation
    • it's highly advised to turn this option on
    • now this option defaults to false but will be default to true after the 1.0 release

0.8.3

Fixed

  • handle when target property is undefined when calling ValidationError.toString()

0.8.2

Added

  • added ValidationError.toString() method for easier debugging
  • added printError method to pretty-print errors in NodeJS or the browser

Fixed

  • fixed wrong type info in ValidatorOptions
  • fixed wrong type info in ValidationSchema (the options key now is optional)
  • corrected IsNumericString to IsNumberString in the README
  • fixed type of host_whitelist and host_backlist in IsURLOptions

0.8.1

Fixed

  • fixed wrong type info in ValidatorOptions

0.8.0 [BREAKING CHANGE]

Added
  • updated validator.js from 7.0.0 to 9.2.0 (Check it's changelog for what has changed.)

    This caused breaking change, if you used the IsUrl decorator to validate localhost as a valid url, from now you must use the require_tld: false option

    @IsUrl({ require_tld: false})
    url: string;
  • added @IsInstance decorator and validator.isInstance(value, target) method.

  • changed @IsNumber decorator has been changed to @IsNumber(options: IsNumberOptions)
  • added option to strip unknown properties (whitelist: true)
  • added option to throw error on unknown properties (forbidNonWhitelisted: true)
  • added @Allow decorator to prevent stripping properties without other constraint

Fixed

  • fixed issue with @IsDateString now it allow dates without fraction seconds to be set
  • fixed issue with @IsDateString now it allow dates without with timezones to be set
  • @ValidateNested correctly generates validation error on non object and non array values

0.6.7

Fixed

  • fixed issue with @ValidateNested when nested property is not defined and it throw an error (#59)

0.6.5

Fixed

  • fixed bugs with @IsUrl, @IsEmail and several other decorators

0.6.4

Added

  • added @IsMilitaryTime decorator.

0.6.3

Added

  • added validateOrReject method which rejects promise instead of returning array of errors in resolved result

0.6.1

Added

  • added @IsArray decorator.

0.6.0 [BREAKING CHANGE]

Added

  • breaking change with @ValidateNested on arrays: Validator now groups the validation errors by sub-object, rather than them all being grouped together. See #32 for a demonstration of the updated structure.
  • added @ValidateIf decorator, see conditional validation in docs.

0.5.0 [BREAKING CHANGE]

Added

  • async validations must be marked with { async: true } option now.

    This is optional, but it helps to determine which decorators are async to prevent their execution in validateSync method.

  • added validateSync method that performs non asynchronous validation and ignores validations that marked with async: true.

  • there is a breaking change in registerDecorator method. Now it accepts options object.
  • breaking change with @ValidatorConstraint decorator. Now it accepts option object instead of single name.

0.4.1

Fixed

  • fixed issue with wrong source maps packaged

0.4.0 [BREAKING CHANGE]

Added

  • everything should be imported from "class-validator" main entry point now
  • ValidatorInterface has been renamed to ValidatorConstraintInterface
  • contain can be set in the main entry point now
  • some decorator's names changed. Be aware of this
  • added few more non-string decorators
  • validator now returns array of ValidationError instead of ValidationErrorInterface. Removed old ValidationError
  • removed all other validation methods except validator.validate
  • finally validate method is async now, so custom async validations are supported now
  • added ability to validate inherited properties
  • added support of separate validation schemas
  • added support of default validation messages
  • added support of special tokens in validation messages
  • added support of message functions in validation options
  • added support of custom decorators
  • if no groups were specified, decorators with groups now are being ignored
  • changed signature of the ValidationError. Now if it has nested errors it does not return them in a flat array

Fixed

  • fixed all decorators that should not work only with strings

0.3.0

Added

  • package has changed its name from validator.ts to class-validator.
  • sanitation functionality has been removed from this library. Use class-sanitizer instead.