😎
Nest.js Swaggerの@ApiResponseでジェネリクス的なことがしたい
こういうことがしたい。
(ApiResponseでSwaggerで表示される型を動的に変えたい)
しかしこれだとSwaggerで正しく表示されない。
// 動かないコード
class ResultDataDto<T> {
@ApiProperty()
resultData: T;
}
// Controllerで
@Get('/user')
@ApiOkResponse({ type: ResultDataDto<UserResDto> })
ちゃんと表示するには、以下のようにカスタムデコレータを作成して、schemaを定義する必要がある。
import { applyDecorators } from '@nestjs/common';
import { ApiOkResponse, getSchemaPath, ApiExtraModels } from '@nestjs/swagger';
export function ResultDataResponse(model: any) {
return applyDecorators(
ApiExtraModels(model),
ApiOkResponse({
schema: {
properties: {
resultData: { $ref: getSchemaPath(model) }
},
},
}),
);
}
// Controllerで
@Get('/user')
@ResultDataResponse(UserResDto)
ApiExtraModels
はDTOのimportをよしなにやってくれるメソッドらしい(これがないとCould not resolve reference: #/components/schemas/***
となる)。
ページネーションのレスポンス
ページネーションで表示するときに、こんな感じでデコレーターを作っておくと便利。
export class PaginatedResponseDto<T> {
data: T[]
@ApiProperty()
totalCount: number
@ApiProperty()
offset: number
@ApiProperty()
limit: number
}
// カスタムデコレーター
export const ApiOkResponsePaginated = <DataDto extends Type<unknown>>(dataDto: DataDto) =>
applyDecorators(
ApiExtraModels(PaginatedResponseDto, dataDto),
ApiOkResponse({
schema: {
allOf: [
{ $ref: getSchemaPath(PaginatedResponseDto) },
{
properties: {
data: {
type: 'array',
items: { $ref: getSchemaPath(dataDto) },
},
},
},
],
},
})
)
ページネーションについては、以下の記事で説明されています。
Discussion