在 POST 上动态更改 @Body 类型

Dynamically change @Body type on POST

我创建了一个 class 来从我的控制器中扩展,所以在我的 POST 中,当我像这样定义 BODY 参数时

@Body() create: any

但我正在使用 swagger,所以我想显示架构。 我试过这种方法:

type dto = {
  one: OneDto
  two: TwoDto
}

然后

@Body() create: dto['one']

但无论如何它都没有显示架构。 有什么建议吗?

类型在运行时不存在,AFIAK @nestjs/swagger 插件在运行时依赖它们。所以你甚至不能使用@Body() create: InterfaceCreate。你必须有一些具体的class

这可能会帮助您解决:How to generate Generics DTO with nestjs/swagger(一个 post 由一个对 @nestjs/swagger 包贡献很大的人制作的)

我解决这个问题不是通过动态更改类型,而是创建一个控制器工厂。我用这个 并根据我的需要进行修改。

export function CrudController<T, C, U, Q>(
  createDto: Type<C>,
  updateDto: Type<U>,
  queryDto: Type<Q>
): Type<ICrudController<T, C, U, Q>> {
  const createPipe = new AbstractValidationPipe(
    { /* whitelist: true, */ transform: true /* forbidNonWhitelisted: true */ },
    { body: createDto }
  );
  const updatePipe = new AbstractValidationPipe(
    { /* whitelist: true, */ transform: true },
    { body: updateDto }
  );
  const queryPipe = new AbstractValidationPipe(
    { /* whitelist: true, */ transform: true },
    { query: queryDto }
  );

  class CRUD<T, C, U, Q> implements ICrudController<T, C, U, Q> {
    constructor(protected readonly service: CrudService<T, C, U, Q>) {}
    // protected ;

    @Post()
    @UsePipes(createPipe)
    @ApiBody({ type: createDto })
    @ApiCreatedResponse({
      description: "Created succesfully.",
      type: CreatedDto,
    })
    @ApiBadRequestResponse({ type: ResponseDto })
    @ApiForbiddenResponse({ type: ResponseDto })
    @ApiConflictResponse({ type: ResponseDto })
    create(
      @Body() body: C
    ) {
      return this.service.createAsync(body);
    }

    @Get()
    @UsePipes(queryPipe)
    @ApiOkResponse({ description: "Retrieved succesfully.", type: queryDto })
    @ApiBadRequestResponse({ type: ResponseDto })
    @ApiForbiddenResponse({ type: ResponseDto })
    read(): Promise<any> {
      return this.service.readAsync();
    }

    @Get(":id")
    @ApiOkResponse({ description: "Retrieved succesfully.", type: queryDto })
    @ApiBadRequestResponse({ type: ResponseDto })
    @ApiForbiddenResponse({ type: ResponseDto })
    readOne(
      @Param("id", ParseIntPipe) id: number
    ): Promise<Q> {
      return this.service.readAsync(null, { id: id });
    }

    @Patch(":id")
    @UsePipes(updatePipe)
    @ApiBody({ type: updateDto })
    @ApiBadRequestResponse({ type: ResponseDto })
    @ApiForbiddenResponse({ type: ResponseDto })
    update(
      @Param("id", ParseIntPipe) id: number,
      @Body() body: U
    ): any {
      return this.service.updateAsync(body, { id: id });
    }

    @Delete(":id")
    @ApiBadRequestResponse({ type: ResponseDto })
    @ApiForbiddenResponse({ type: ResponseDto })
    delete(
      @Param("id", ParseIntPipe) id: number
    ): any {
      return this.service.deleteAsync(id);
    }
  }
  return CRUD;
}