NestJS中如何同时使用mapped-types、Swagger与class-transformer
问题根因
你遇到的报错本质是DTO之间存在循环依赖,而非mapped-types、swagger、class-transformer三个库本身不兼容。@nestjs/swagger的PickType执行时,循环引用的目标类还未完成初始化,值为undefined,因此触发原型读取失败的报错。
以下是三个基于mapped-types的可行解决方案,不需要手动重写所有字段:
方案1:继续使用@nestjs/swagger的PickType,修复循环依赖
通过惰性加载的方式让依赖的类在实际使用时才加载,避免初始化时取值为undefined:
- 把
UserDto中@ApiProperty的type属性改为函数返回形式
// UserDto代码修改部分 @ApiProperty({ isArray: true, type: () => ProjectDescriptorDto, })
- 把
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
相关产品推荐
相关产品推荐

