Menu
CoddyTech

サービス

CoddyのNode.jsジャーニー「TypeScriptとNestJS」セクションの一部。レッスン 9/24。

コントローラーがタスク自体を保持しているため、アプリのほかの部分からタスクにアクセスできません。データとロジックはプロバイダーに置きます。プロバイダーとは、Nestが作成し、要求したクラスに渡すクラスです。

@Injectable()
export class BooksService {
    private books = [{ title: 'Dune' }];
}

@Controller('books')
export class BooksController {
    constructor(private readonly booksService: BooksService) {}
}

@Injectable()はクラスをマークし、モジュールはそれをprovidersに登録します。クラスはコンストラクターで名前を指定してプロバイダーを要求します。これが依存性注入です。引数の前に付けるprivate readonlyはTypeScriptの省略記法で、フィールドthis.booksServiceを作成し、Nestから渡された値を格納します。Nestは引数の型を読み取ります。コンパイラーはデコレーターが付いたクラスの型を保持します。Nestはプロバイダーを登録したモジュールごとにインスタンスを1つ作成し、それを要求するモジュール内のすべてのクラスに同じインスタンスを渡します。データは共有され、テストでは代わりに偽物を渡すこともできます。

このレッスンは、コントローラーがすでにthis.tasksServiceを呼び出しているところから始まります。

challenge icon

チャレンジ

簡単

このステップでは、Status Codes and Errors のプロジェクトファイル(src/tasks/tasks.controller.ts など)ではなく、コースで用意された Nest のタスクトラッカープロジェクトを開きます。これまでの作業は、前のレッスンにそのまま残ります。src/tasks/tasks.service.ts を編集する前に、用意されたファイルを読んでください。このコピーには Nest のタスクルートが含まれており、コントローラーはサービスに処理を委譲するよう準備されています。

タスクはコントローラーの中にあるため、アプリのほかの部分からはアクセスできません。タスクを所有するクラスであるサービスに移しましょう。Nest はサービスを一度作成し、サービスを必要とする各クラスに渡します。コントローラーはすでにサービスを呼び出すよう書き換えられています。あなたの作業は、サービスを完成させ、両者をつなぐことです。

  1. src/tasks/tasks.service.ts で、@nestjs/common の @Injectable() を使って、クラス TasksService にマークを付けます。これにより、Nest がクラスを作成して渡せるようになります。
  2. 同じクラスに、メソッド create(title) を書きます。このメソッドは、次に使える id(this.tasks の中で最大の id より 1 大きい値)、そのタイトル、および done: false を持つタスクを作成します。そのタスクを this.tasks に追加して返します。コントローラーの POST /tasks は、リクエストボディから取得したタイトルを渡してこのメソッドを呼び出します。
  3. id が数値であるメソッド remove(id) を書きます。その id のタスクがない場合は、findOne と同様に 404 を返さなければなりません。まず this.findOne(id) を呼び出してください。このメソッドは例外をスローします。その後、タスクを this.tasks から削除します。戻り値はありません。
  4. src/tasks/tasks.module.ts で、./tasks.service から TasksService をインポートします。次に、controllers の隣に providers リストをモジュールに追加し、その中に TasksService を入れます。Nest が作成するのは、モジュールがそこに登録したクラスだけです。
  5. src/tasks/tasks.controller.ts で、TasksController 内のコメントを、パラメーターを1つ受け取るコンストラクターに置き換えます。パラメーターは private readonly tasksService: TasksService と書きます。Nest は型 TasksService を見て、そのサービスを渡します。また、パラメーターの前にある private readonly は、渡された値を保持するフィールド this.tasksService も作成します。これが、以下のメソッドですでに使われている名前です。

試してみましょう: /tasks に POST { "title": "Buy milk" } を送信します。201 と次の応答が返ります。

{ "id": 4, "title": "Buy milk", "done": false }

GET /tasks を送信すると、タスクが4つ返り、最後に Buy milk が表示されます。DELETE /tasks/4 を送信すると、204 が返ります。DELETE /tasks/99 を送信すると、"message": "Task 99 not found" とともに 404 が返ります。

自分で試してみよう

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

export interface Task {
    id: number;
    title: string;
    done: boolean;
    createdAt?: string;
}

// このクラスを Nest が注入できるプロバイダーにしてください。
export class TasksService {
    private tasks: Task[] = [
        { id: 1, title: 'Write the README', done: true, createdAt: '2026-01-05T09:00:00.000Z' },
        { id: 2, title: 'Fix the login bug', done: false, createdAt: '2026-01-06T14:30:00.000Z' },
        { id: 3, title: 'Plan the sprint', done: false, createdAt: '2026-01-07T08:15:00.000Z' },
    ];

    findAll(done?: string): Task[] {
        if (done === undefined) {
            return this.tasks;
        }
        return this.tasks.filter((task) => task.done === (done === 'true'));
    }

    findOne(id: number): Task {
        const task = this.tasks.find((task) => task.id === id);
        if (!task) {
            throw new NotFoundException(`Task ${id} not found`);
        }
        return task;
    }

    // ここに create(title) と remove(id) を実装してください。
}
quiz icon腕試し

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

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

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