Nodejs 请教一个 nestjs 创建 updateDto 的问题

发布于 1周前 作者 yibo5220 来自 nodejs/Nestjs

Nodejs 请教一个 nestjs 创建 updateDto 的问题
大家好,请教一个关于 ‘class-validator’ 和 PartialType 的问题:

在用 ‘@nestjs/swagger’ 的 PartialType 创建 updateDto 时,我发现了一个问题,PartialType 会为 createDto 里的每个属性添加 @IsOptional() 修饰器,导致前端传入的所有值为 null 的属性都能跳过 ‘class-validator’ 的验证,顺利通过 ValidationPipe

而 undefined 和 null 对于 ORM ,例如 typeorm 有不同的含义,例如:
usersRepository.update({ name: null }) 表示将字段 name 更新为 null
usersRepository.update({ name: undefined }) 表示不对字段 name 进行更新

最终本该 not null 的字段接受了一个 null 值,导致数据库抛错 NOT NULL constraint failed


这应该是一个常见的应用场景吧?没人遇到类似的问题吗?
https://stackoverflow.com/questions/70380391/how-to-mark-certain-fields-as-nullable-or-not-nullable-in-nestjs-request-validat
https://stackoverflow.com/questions/68622366/nestjs-update-is-returning-null-for-other-fields-thereby-giving-validation-issue


附上测试代码,是我实现的方式不对吗?我在网上都搜不到这个问题
https://github.com/yodhcn/mapped-types-example


7 回复

可以重写属性添加修饰器
export class UpdateUserDto extends PartialType(CreateUserDto) {
()
()
name?: string;
}


#1 是的,可以重写,但如果我多数字段都是 NOT NULL 的活,我也只能将每个字段手动重写,PartialType 失去了它的存在意义,这是否意味着 PartialType 设计的不合理?

参考 https://github.com/typestack/class-validator/issues/579

应该重写成 ((object, value) => value !== undefined)

也不好说是 PartialType 不好,更多可能是 ()的问题

而且这个问题在 class-validator 的 issues 里讨论的更多

在你的 update 或者 create 里加上 || ‘’ ?

不从 dto 直接更新数据库

我觉得是这样的,而且也不应该放在 /swagger 包下

在 NestJS 中,创建 updateDto(数据传输对象)是一个常见的任务,通常用于更新实体时接收部分或全部字段的数据。updateDto 通常包含可选字段,以允许部分更新。以下是如何创建一个简单的 updateDto 的示例。

假设我们有一个 User 实体,其结构如下:

export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  email: string;

  // 其他字段...
}

为了创建一个 UpdateUserDto,我们可以这样做:

import { PartialType } from '@nestjs/mapped-types';
import { CreateUserDto } from './create-user.dto'; // 假设已有一个创建用户的Dto

export class UpdateUserDto extends PartialType(CreateUserDto) {}

这里我们使用了 @nestjs/mapped-types 包中的 PartialType,它会将 CreateUserDto 中的所有字段变为可选字段。如果 CreateUserDto 如下:

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

export class CreateUserDto {
  @IsString()
  readonly name: string;

  @IsEmail()
  readonly email: string;

  // 其他字段及其验证器...
}

那么 UpdateUserDto 将自动继承 CreateUserDto 的结构,但所有字段都会变成可选的,非常适合用于更新操作。

这种方式不仅减少了重复代码,还保证了 updateDtocreateDto 之间的一致性。

回到顶部