0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

NestJS で Interface を使った Dependency Injection を実現する

Posted at

NestJS は文字列のトークンを実体クラスに置き換えて DI することができる。

これを使ってクラス間をインターフェースで結びつけることができる。

インターフェースの定義

以下UsersServiceというサービスをインターフェースで DI できるようにする例を記載する。

インターフェースを定義する。

src/users/interfaces/users.service.interface.ts
import { CreateUserDto } from "../dto/create-user.dto";
import { UserEntity } from "../entities/user.entity";

export interface IUsersService {
  /**
   * ユーザを取得する
   * @param id ID
   */
  findOne(id: string): Promise<UserEntity>;

  // 長いので省略
}

実装

export class UsersService implements IUsersServiceみたいな感じでインターフェースの実装を行う。

src/users/users.service.ts
import { Inject, Injectable } from "@nestjs/common";
import { TYPES } from "src/types";
import { IUsersRepository } from "./interfaces/users.repository.interface";
import { IUsersService } from "./interfaces/users.service.interface";
// 他のimportは省略

@Injectable()
export class UsersService implements IUsersService {
  constructor(
    @Inject(TYPES.UsersRepository)
    private readonly usersRepository: IUsersRepository
  ) {}

  async findOne(id: string): Promise<UserEntity> {
    // 実装する
    return await this.usersRepository.findOne(id);
  }

  // 長いので省略
}

文字列トークンの定義

インターフェースの分だけ定数を定義する。

src/types.ts
export const TYPES = {
  UsersRepository: Symbol.for("UsersRepository"),
  UsersService: Symbol.for("UsersService"),
  TodosRepository: Symbol.for("TodosRepository"),
  TodosService: Symbol.for("TodosService"),
  LoggerService: Symbol.for("LoggerService"),
  AuthService: Symbol.for("AuthService"),
};

モジュールの記載

以下のprovidersのように{provide: <文字列トークン>, useClass: 実体クラス}で記述する。

src/users/users.module.ts
import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { TYPES } from "src/types";
import { UsersRepository } from "./users.repository";
import { UsersService } from "./users.service";
// 他のimportは省略

@Module({
  // このモジュールが動くのに必要なモジュールを記述する。
  imports: [TypeOrmModule.forFeature([UserEntity])],
  // このモジュールが提供するコントローラを記述する。
  controllers: [UsersController],
  // このモジュール内で使うサービスを記述する。
  providers: [
    { provide: TYPES.UsersRepository, useClass: UsersRepository },
    { provide: TYPES.UsersService, useClass: UsersService },
  ],
  // このモジュールが他のモジュールへ提供するサービスを記述する。
  exports: [TYPES.UsersService],
})
export class UsersModule {}

DI

コンストラクタにて@Inject()を使って DI する。

src/users/users.controller.ts
import { Inject } from "@nestjs/common";
import { TYPES } from "src/types";
import { IUsersService } from "./interfaces/users.service.interface";
// 他のimportは省略

@Controller("users")
export class UsersController {
  constructor(
    @Inject(TYPES.UsersService) private readonly usersService: IUsersService
  ) {}

  // 省略
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?