How to Inject NestJS Service from another Module

Updated: January 1, 2024 By: Guest Contributor Post a comment

Introduction

In NestJS, services encapsulate business logic and can be shared across different parts of your application. However, when services are defined in different modules, you need to understand the module dependency injection system to use them. This tutorial will guide you on how to inject a service from one module into another within a NestJS application using the latest syntax and TypeScript best practices.

Prerequisites

Before you begin, ensure you have the following installed:

  • Node.js (14.x or later)
  • NestJS CLI
  • TypeScript

Ensure you’re familiar with TypeScript and the basics of NestJS, including modules, controllers, and services (providers).

Creating Your Modules and Services

First, let’s create two modules: UsersModule and OrdersModule. The UsersService from the UsersModule will be injected into the OrdersModule.

nest g module Users
nest g module Orders

nest g service Users
nest g service Orders

Exporting the Service

To be able to use UsersService in OrdersModule, you must first export it in UsersModule.

@Module({
  providers: [UsersService],
  exports: [UsersService]
})
export class UsersModule {}

Importing the Module

Next, import UsersModule into OrdersModule to make UsersService available for injection.

@Module({
  imports: [UsersModule],
  providers: [OrdersService]
})
export class OrdersModule {}

InjecSystemService

To inject UsersService into OrdersService, use the @Injectable() decorator and specify the dependency in the constructor.

@Injectable()
export class OrdersService {
  constructor(private usersService: UsersService) {}

  // Your methods using usersService here
}

Advanced Usage: Custom Providers with Module Ref

For advanced scenarios, you might want to manipulate providers or dynamically provide them. Imagine a scenario where you have different implementations based on certain criteria, and you want the consuming module to decide the actual implementation it requires. Here’s a pattern using ModuleRef to resolve providers dynamically in NestJS.

@Injectable()
export class OrdersService {
  private usersService: UsersService;

  constructor(private moduleRef: ModuleRef) {
    this.usersService = this.moduleRef.get(UsersService, { strict: false });
  }

  // Your methods using usersService here
}

Understanding the Global Module

Sometimes, you might have a service that should be available throughout your application. You can make a module global with the @Global() decorator. This should be used sparingly and only for truly application-wide services.

@Global()
@Module({
  providers: [CommonService],
  exports: [CommonService]
})
export class CommonModule {}

Add the global module to the root module’s imports array, and its services will accessible across the entire application without importing the module in each feature module explicitly.

Conclusion

Understanding service injection across modules is pivotal for structuring your NestJS application effectively. This tutorial covered how to export and import services, advanced dynamic provider techniques with ModuleRef, and leveraging global modules for widespread services. Remember that keeping your modules and providers well-organized will lead to a maintainable and scalable codebase.