Imports by interface

Implementation flexibility and prevent circular dependency.

Imports by interface provide greater implementation flexibility and prevent circular dependency. With interface implementation, it's much easier to test our module, as we can create services that implement this interface.

Understand how it works.

Using Nest, you can implement interfaces instead of the service, and with that, the service starts to implement this interface, for example.

cats.interface.ts
export interface ICatsService {
  getName(): string;
}
cats.service.ts
import { Injectable } from '@nestjs/common';
import type { ICatsService } from './cats.interface';

@Injectable()
export class CatsService implements ICatsService {
  getName() {
    return 'Niro';
  }
}

To inject our service into another, it would look like this.

app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CatsService } from './cats/cats.service';

@Module({
  controllers: [AppController],
  providers: [
    AppService,
    {
      provide: 'ICatsService',
      useClass: CatsService,
    },
  ],
})
export class AppModule {}
app.service.ts
import { Inject, Injectable } from '@nestjs/common';
import type { ICatsService } from './cats/cats.interface';

@Injectable()
export class AppService {
  constructor(
    @Inject('ICatsService')
    private readonly catsService: ICatsService,
  ) {}

  getName() {
    return this.catsService.getName();
  }
}

Last updated