Menu
CoddyTech

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の検証ではデコレーターで記述されたルールを読み取りますが、デコレーターにはクラスが必要です。それについては次のレッスンで学びます。

challenge icon

チャレンジ

簡単

クライアントは、すでに完了しているタスクを作成できるようになりました。DTO(リクエストボディに含まれるフィールドを列挙するクラス)でPOST /tasksのボディを記述し、サービスまでそのまま渡しましょう。

  1. src/tasks/dto/create-task.dto.tsで、クラスCreateTaskDtoに2つのフィールドを定義します。titleは文字列、doneは省略可能な真偽値です。
  2. src/tasks/tasks.controller.tsで、メソッドcreateを変更します。@Body()パラメーターの型を{ title: string }ではなくCreateTaskDtoにします。タイトルだけではなく、DTO全体をサービスに渡します。
  3. 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 {}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

TypeScriptとNestJSのすべてのレッスン

自分で練習してみよう: Expressプレイグラウンド