验证不适用于 Partial<DTO> - NestJS

Validation does not work with Partial<DTO> - NestJS

我想在我的 CRUD API 上应用服务器端验证。有问题的实体称为 Employee。我正在使用 employee.dto(如下所示)来创建和更新端点。

class-validator 包在 create 方法上运行良好,但当我在更新方法中将它与 Partial<EmployeeDTO> 一起使用时,它会忽略 DTO 中的所有规则。

请参考以下代码。

套餐

"class-transformer": "^0.2.3",
"class-validator": "^0.10.0",

员工 DTO

import { IsString, IsNotEmpty, IsEmail, IsEnum } from 'class-validator';

import { EmployeeRoles } from '../../entities/employee.entity';

export class EmployeeDTO {
  @IsString()
  @IsEmail()
  @IsNotEmpty()
  email: string;

  @IsString()
  @IsNotEmpty()
  password: string;

  @IsString()
  @IsNotEmpty()
  username: string;

  @IsString()
  @IsNotEmpty()
  fullName: string;

  @IsString()
  @IsNotEmpty()
  @IsEnum(EmployeeRoles)
  role: string;
}

员工控制器

import {
  Controller,
  Param,
  Post,
  Body,
  Put,
  UsePipes,
} from '@nestjs/common';

import { EmployeeDTO } from './dto/employee.dto';
import { EmployeeService } from './employee.service';
import { ValidationPipe } from '../shared/pipes/validation.pipe';

@Controller('employee')
export class EmployeeController {
  constructor(private employeeService: EmployeeService) {}

  @Post()
  @UsePipes(ValidationPipe)
  addNewEmployee(@Body() data: EmployeeDTO) {
    return this.employeeService.create(data);
  }

  @Put(':id')
  @UsePipes(ValidationPipe)
  updateEmployee(@Param('id') id: number, @Body() data: Partial<EmployeeDTO>) {
    return this.employeeService.update(id, data);
  }
}

可能的解决方案

我想解决的问题是为 createupdate 方法创建单独的 DTO,但我不喜欢重复代码的想法。

对于这个答案,我将进行猜测并假设您使用 NestJS' documentation 中提供的 ValidationPipe 或其近似导数。

您的 updateEmployee 方法的参数 data 类型是 Partial,它不发出任何类型元数据。 ValidationPipe 使用 class-transformer 模块实例化它,导致 class-validator 模块验证普通对象,而不是 EmployeeDTO.

要使验证生效,data 参数的类型应为 class。 您可以制作单独的 DTO 来创建和更新您的实体,或者如果您想保留一个 class.

,则使用 validation groups

为了实现部分验证,可以使用PartialType效用函数。你可以在这里读到它: https://docs.nestjs.com/openapi/mapped-types#partial

您需要创建另一个 class:

export class UpdateEmployeeDTO extends PartialType(EmployeeDTO) {}

然后在您的控制器中,您需要将 @Body data Partial<EmployeeDTO> 的类型替换为 UpdateEmployeeDto。它应该是这样的:

@Patch(':id')
@UsePipes(ValidationPipe)
updateEmployee(@Param('id') id: number, @Body() data: UpdateEmployeeDTO) {
    return this.employeeService.update(id, data);
}

请记住,您应该从 @nestjs/mapped-types 导入 PartialType,而不是像文档中建议的那样从 @nestjs/swagger 导入。有关更多信息,请参见 here