class-transformer icon indicating copy to clipboard operation
class-transformer copied to clipboard

@Expose ignores default value

Open rostislav-kondratenko-lmnd opened this issue 2 years ago • 4 comments

Description

When using @Expose with a default value, the default value is ignored

export class ExampleDTO {
  @IsBoolean()
  @Type(() => Boolean)
  booleanValue = false;

  @IsNumber()
  @Min(4)
  @Type(() => Number)
  digits = 6;
}

This works fine and produces expected: {booleanValue: false, digits: 6} on empty input. However:

export class ExposeExampleDTO {
  @IsBoolean()
  @Type(() => Boolean)
  @Expose({ name: 'boolean_value' })
  booleanValue = false;

  @IsNumber()
  @Min(4)
  @Type(() => Number)
  @Expose({ name: 'dgt' })
  digits = 6;
}

fails validation as it produces '{}' without validation on empty input.

Expected behavior

Parameters with @Expose decorator should assume default value from the class declaration when the exposed parameter is undefined in the source.

Actual behavior

Parameters with @Expose decorator ignore default value when the exposed parameter is undefined in the source and are undefined.

have_you_solved_this_problem

yonghui666 avatar Mar 30 '23 02:03 yonghui666

@yonghui666 no, I haven't. Had to skip the validation here and validate it later in the code.

Can confirm this issue. We want to have a boolean toggle-state attribute which is not passed from outside (e.g. public active: boolean = false). But during initialization, this attribute is always undefinded while the other properties from outside are deserialized and set.

Moongazer avatar Nov 06 '23 09:11 Moongazer

Hello @rostislav-kondratenko-lmnd,

You can use the exposeDefaultValues option when calling plainToInstance. With this option transformation will preserve the default value, when not set in plain.

diffy0712 avatar May 05 '24 20:05 diffy0712

For the NestJS users:

Follow the docs at https://docs.nestjs.com/techniques/validation#auto-validation to configure your app. Customize the validation pipe as demonstrated below.

export const DEFAULT_VALIDATION_PIPE_OPTIONS: ValidationPipeOptions = {
  transform: true,
  ...
  transformOptions: {
    // NOTE: This is necessary to ensure default values are respected when 
    // using the Expose decorator from class-transformer.
    exposeDefaultValues: true,
  },
};
export const validationPipe = new ValidationPipe(
  DEFAULT_VALIDATION_PIPE_OPTIONS
);

app.useGlobalPipes(validationPipe);

clintonb avatar May 16 '24 07:05 clintonb

Thank you @clintonb!

Closing as answered. If you have any questions left feel free to comment on this issue.

diffy0712 avatar May 16 '24 08:05 diffy0712