NestJS中使用interface而非class作为DTO时如何实现Swagger文档配置?
解决方案
报错原因
TypeScript 接口属于编译期类型,运行时会被完全擦除,而@ApiProperty这类装饰器需要依附于运行时真实存在的类实例结构才能生效,因此无法直接作用在接口属性上。
可选实现方案(无需手动编写DTO类)
方案1:手动定义Swagger Schema,直接绑定到接口
你可以单独定义接口对应的Swagger结构,在接口方法上通过@ApiBody/@ApiResponse等装饰器直接绑定,原有interface不需要做任何修改:
- 定义接口和对应Schema
// 原有interface保持不变 export interface ProjectInterface { id: string; title: string; description: string; } // 手动定义Swagger识别的结构 export const ProjectSwaggerSchema = { type: 'object', properties: { id: { type: 'string' }, title: { type: 'string', description: '项目名称' }, description: { type: 'string', description: '项目描述' } }, required: ['id', 'title'] // 按需配置必填字段 } as const;
- 绑定到对应接口
示例:给请求体绑定结构
import { ApiBody } from '@nestjs/swagger'; @Post() @ApiBody({ schema: ProjectSwaggerSchema }) createProject(@Body() project: ProjectInterface) { // 业务逻辑 }
示例:给返回值绑定结构
import { ApiOkResponse } from '@nestjs/swagger'; @Get(':id') @ApiOkResponse({ schema: ProjectSwaggerSchema }) getProject(@Param('id') id: string): ProjectInterface { // 业务逻辑 }
方案2:通过Zod推导类型和Schema(零重复代码)
如果不想手动写两份结构,可以用Zod定义校验规则,同时推导TypeScript类型和Swagger Schema,全程不需要手动编写DTO类:
- 安装依赖(如果未安装)
npm i zod @nestjs/swagger
- 定义结构,同时生成类型和Swagger可识别的DTO
import { z } from 'zod'; import { createZodDto } from '@nestjs/swagger'; // 定义Zod结构,自带字段描述 const ProjectSchema = z.object({ id: z.string(), title: z.string().describe('项目名称'), description: z.string().describe('项目描述') }); // 导出类型给TypeScript做类型校验,和原生interface使用体验完全一致 export type ProjectInterface = z.infer<typeof ProjectSchema>; // 自动生成Swagger需要的DTO,不需要手动编写类结构 export class ProjectDto extends createZodDto(ProjectSchema) {}
- 接口直接使用
@Post() createProject(@Body() project: ProjectInterface) { // 业务逻辑 }
内容的提问来源于stack exchange,提问作者Anirudh Suri
相关产品推荐
相关产品推荐

