You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS中如何同时使用mapped-types、Swagger与class-transformer

问题根因

你遇到的报错本质是DTO之间存在循环依赖,而非mapped-types、swagger、class-transformer三个库本身不兼容。@nestjs/swagger的PickType执行时,循环引用的目标类还未完成初始化,值为undefined,因此触发原型读取失败的报错。

以下是三个基于mapped-types的可行解决方案,不需要手动重写所有字段:


方案1:继续使用@nestjs/swagger的PickType,修复循环依赖

通过惰性加载的方式让依赖的类在实际使用时才加载,避免初始化时取值为undefined:

  1. 把UserDto中@ApiProperty的type属性改为函数返回形式
// UserDto代码修改部分
@ApiProperty({
  isArray: true,
  type: () => ProjectDescriptorDto,
})
  1. 把ProjectDto中UserDescriptorDto的引用改为动态导入,避免加载时循环依赖
// ProjectDto代码修改部分
@Expose()
@Type(() => require('./user-descriptor.dto').UserDescriptorDto)
starredBy: UserDescriptorDto[];

修改完成后即可同时保留Swagger自动生成、class-transformer类型转换、mapped-types精简代码的能力。


方案2:使用@nestjs/mapped-types的PickType,启用Swagger CLI插件

如果你不想修改现有代码的依赖逻辑,可以使用@nestjs/mapped-types的PickType,同时开启Swagger的CLI自动注解插件,插件会自动为mapped-types生成的类补全Swagger元数据,不需要手动添加@ApiProperty:
在项目根目录的nest-cli.json中增加插件配置:

{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "plugins": ["@nestjs/swagger/plugin"]
  }
}

这个方案零业务代码侵入,仅需修改编译配置即可同时满足三个库的使用需求。


方案3:手动声明DTO字段(现有临时方案)

如果上述方案都不满足你的使用场景,也可以继续使用你当前的手动实现方式:

SomeDescriptorDto implements Pick<SomeDto, 'id' | 'title'> {
  @Expose()
  @ApiProperty()
  id: number;

  @Expose()
  @ApiProperty()
  title: string;
}

这种方式灵活性最高,只是需要手动维护字段和装饰器的同步。


内容的提问来源于stack exchange,提问作者JDU

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 09:15:01