Out-of-the-box support for validation of array of objects is kind of scarce in NestJS so far.
Please have at look at my solution:
The main point is to write and then to use your custom IsArrayOfObjects
decorator that will contain the validation logic + @Type
decorator from class-transformer
module.
import { Type } from 'class-transformer';
import {
IsString,
registerDecorator,
ValidateNested,
ValidationArguments,
ValidationOptions,
} from 'class-validator';
export function IsArrayOfObjects(validationOptions?: ValidationOptions) {
return (object: unknown, propertyName: string) => {
registerDecorator({
name: 'IsArrayOfObjects',
target: object.constructor,
propertyName,
constraints: [],
options: validationOptions,
validator: {
validate(value: any): boolean {
return (
Array.isArray(value) &&
value.every(
(element: any) =>
element instanceof Object && !(element instanceof Array),
)
);
},
defaultMessage: (validationArguments?: ValidationArguments): string =>
`${validationArguments.property} must be an array of objects`,
},
});
};
}
Suppose we have this NestedDTO
:
export class NestedDTO {
@IsString()
someProperty: string;
}
Then we can simply use it for defining like:
@IsArrayOfObjects()
@ValidateNested()
@Type(() => NestedDTO)
nested: NestedDTO[];
However, this solution will allow empty array to be passed. Then you can add extra condition in IsArrayOfObjects
like value.length > 0
and also correct its defaultMessage
.