created: 2021-05-02T04:11:30.000Z
NestJS/class-transformer でPOSTされなかったパラメータにデフォルトを設定する
前回までのあらすじ
文字列で渡ってきた "2011-01-01 12:34:56" という文字列を new Date("2011-01-01 12:34:56") された状態で扱うことはできるようになったが、今度はこれにデフォルト値を入れた状態でコントローラが受け取るための方法。
たとえば、expireAt というフィールドがあって、これが null でPOSTされてきたときに二ヶ月後のDateが入った状態で処理を開始したい場合はこんなコードを書けばよい。
import { addMonths } from 'date-fns';
import { Type, Transform } from 'class-transformer';
export class CreateSampleDto {
@IsDate()
@IsNotEmpty()
@Type(() => Date)
@Transform(({ value }) => value || addMonths(new Date(), 1), {
toClassOnly: true,
})
expireAt: Date;
}
Caveat
NestJS の ValidationPipe が undefined だったフィールドは処理してくれないので、falsyな値をつけてPOSTしないと期待通りに動作しない。
つまり、この値をPOSTした場合は期待通り二ヶ月後の日付が入るが
{"id": 1, "expireAt": null}
{"id": 1, "expireAt": "0"}
こんな値をPOSTした場合は、そもそもデフォルト値を入れるための処理が呼ばれない。
{"id": 1}
{"id": 1, "expireAt": undefined}
意図せぬ値がDBに入らないように class-validator の IsNotEmpty を使うと、undefined をPOSTした場合は弾いて、null をPOSTした場合は期待通りに動作するようになる。IsNotEmpty は Transform よりも後に呼ばれるようだ。
苦しい感じでなんとかしているが、クライアント側からするとよくわからない仕様なので本当は undefined を投げられた場合もなんとかしたい。
