DTO
CoddyのNode.jsジャーニー「TypeScriptとNestJS」セクションの一部。レッスン 13/24。
@Body() body: { title: string }は、本文を1か所で説明しているだけで、何も検証していません。{ "title": 42 }はそのまま通過します。DTO(データ転送オブジェクト)は、リクエスト本文に何が含まれるかを記述するクラスです。
export class CreateOrderDto {
customer: string;
express?: boolean;
}
@Post()
create(@Body() dto: CreateOrderDto) {
return this.ordersService.create(dto);
}express?は、省略可能なフィールドを示します。コントローラーとサービスは同じクラスを共有するため、データ構造について共通の認識を持てます。
DTOがインターフェースではなくクラスなのには理由があります。コードの実行時、インターフェースは他の型とともに削除されますが、クラスは残ります。Nestの検証ではデコレーターで記述されたルールを読み取りますが、デコレーターにはクラスが必要です。それについては次のレッスンで学びます。
チャレンジ
簡単クライアントは、すでに完了しているタスクを作成できるようになりました。DTO(リクエストボディに含まれるフィールドを列挙するクラス)でPOST /tasksのボディを記述し、サービスまでそのまま渡しましょう。
src/tasks/dto/create-task.dto.tsで、クラスCreateTaskDtoに2つのフィールドを定義します。titleは文字列、doneは省略可能な真偽値です。src/tasks/tasks.controller.tsで、メソッドcreateを変更します。@Body()パラメーターの型を{ title: string }ではなくCreateTaskDtoにします。タイトルだけではなく、DTO全体をサービスに渡します。src/tasks/tasks.service.tsで、createがタイトルではなくDTOを受け取るように変更します。新しいタスクのtitleにはDTOの値を設定し、doneにもDTOの値を設定します。ボディにdoneがなければfalseにします。idとcreatedAtはこれまでどおりです。
試してみましょう: /tasksにPOSTで{ "title": "Pay rent", "done": true }を送信します。201と、完了済みの新しいタスクが返ります:
{ "id": 4, "title": "Pay rent", "done": true, "createdAt": "2026-10-30T09:15:00.000Z" }(createdAtにはリクエストの時刻が表示されます。){ "title": "Buy milk" }をPOSTで送信すると、"done": falseとともに201が返ります。続いて{ "title": 42 }をPOSTで送信してみましょう。"title": 42が保存され、やはり201が返ります。DTOはボディの内容を記述しますが、まだ何も検証しないためです。次のレッスンでは、Nestがこのリクエストを拒否するようにします。
自分で試してみよう
// POST /tasks のリクエストボディを記述する: title と、クライアントが送信した場合の done。
export class CreateTaskDto {}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
TypeScriptとNestJSのすべてのレッスン
自分で練習してみよう: Expressプレイグラウンド