created: 2021-04-29T07:23:16.000Z

NestJSでPOSTパラメータをクラスのインスタンスに変換して受け取る

NestJS では class-transformer を使って、クライアントから渡されたデータを、jsのクラスのインスタンスにした状態で受け取ることができる。たとえば、日時のデータを文字列からDate型にしてくれるのは便利なのだが、これがびっくりするほど簡単に実現できる。

必要な作業

  • 依存パッケージのインストール
  • DTOクラスにデコレーターで定義を行う
  • ValidationPipeuseGlobalPipes に登録する

依存パッケージのインストール

$ yarn add class-validator class-transformer

ついでで class-validator でのバリデーションも有効にできるので、ついでで入れる。

DTOクラスにデコレーターで定義を行う

この例はコントローラの更新処理の定義。

  @Put(':id')
  update(
    @Param('id') id: string,
    @Body() updateUserDto: UpdateUserDto,
  ) {
    return this.service.update(+id, updateUserDto);
  }

UpdateUserDto を以下のように定義する。

expireAt は日時を表すデータだが、POSTされた文字列をDateにしてくれるよう class-transformer#Type に指定する。

import { IsDate, IsString, IsNotEmpty } from 'class-validator';
import { Type } from 'class-transformer';

export class CreateUserDto {
  @IsString()
  @IsNotEmpty()
  readonly name: string;

  @IsDate()
  @Type(() => Date)
  readonly expireAt: Date;
}

export class UpdateUserDto extends PartialType(CreateUserDto) {}

ValidationPipeuseGlobalPipes に登録する

main.ts で処理を挟み込む。{transform: true} のオプションを渡す。

import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe({ transform: true }));

参考

所感

いままでデコレータって仕様も決まってないし使わない方がいいんじゃないかなと思っていたが、こんなことができるなら仕様変更で多少面倒な思いをしてでも使った方がいいなってなった。