Skip to content

Inconsistent behavior between @IsOptional() and PartialType for handling optional properties #2607

Open
@microCloudCode

Description

@microCloudCode

Description

In NestJS, there is an inconsistency in how optional properties are handled between DTOs using @IsOptional() decorator and DTOs using PartialType. When using @IsOptional(), properties that are not provided in the request are set to undefined, while PartialType completely omits these properties. This creates confusing behavior when working with both types of DTOs.

Minimal code-snippet showcasing the problem

import { IsEmail, IsOptional, IsString } from 'class-validator';
import { PartialType } from '@nestjs/swagger';

export class CreateUserDto {
  @IsEmail()
  email: string;

  @IsString()
  @IsOptional()
  name: string;
}

export class UpdateUserDto extends PartialType(CreateUserDto) {}

// When sending request { email: 'test@example.com' } to both endpoints:

// CreateUserDto output:
console.log(createUserDto); // { email: 'test@example.com', name: undefined }

// UpdateUserDto output:
console.log(updateUserDto); // { email: 'test@example.com' }

Expected behavior

Both @IsOptional() and PartialType should handle optional properties consistently. When a property is not provided in the request, it should be completely omitted rather than being set to undefined. The behavior should be consistent across both approaches:

// Expected output for both DTOs:
// { email: 'test@example.com' }

Actual behavior

Currently, there are two different behaviors:

  1. With @IsOptional():
// CreateUserDto output:
{ email: '[email protected]', name: undefined }
  1. With PartialType:
// UpdateUserDto output:
{ email: '[email protected]' }

This inconsistency can lead to confusion when developers are working with both types of DTOs in the same application. It's particularly problematic when the same property is handled differently depending on whether it's in a create or update operation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: needs triageIssues which needs to be reproduced to be verified report.type: fixIssues describing a broken feature.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions