typestack / class-validator

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

fix: ValidateNested allows empty arrays as objecs #2480

Open Clashsoft opened 4 months ago

Clashsoft commented 4 months ago

Description

The ValidateNested decorator does not check if the value is actually an object. If the entire class consists of optional fields, it will pass validation.

Minimal code-snippet showcasing the problem

import {validate, IsOptional, IsInt, ValidateNested} from 'class-validator';
import {plainToClass, Type} from 'class-transformer';

export class GameSettings {
  @IsOptional()
  @IsInt()
  size?: number;
}

class Game {
  @IsOptional()
  // @IsObject() // with this, it works
  @ValidateNested()
  @Type(() => GameSettings)
  settings?: GameSettings;
}

const badGame = {settings: []};
const game = plainToClass(Game, badGame);

console.log(game); // Game { settings: [] }

validate(game).then(console.log); // []

Expected behavior

A validation error occurs, e.g. settings must be an object or settings must be an instance of GameSettings. This can be achieved with an addition @IsObject() or IsInstance(GameSettings) decorator, though that seems redundant.

Actual behavior

No validation error.