Constructor Injection

Asking for a Dependency

Declare the dependency as a constructor parameter. With private readonly TypeScript creates and assigns the field for you (a parameter property).

src/products/products.service.ts

import { Injectable } from '@nestjs/common';
import { PricingService } from './pricing.service';

@Injectable()
export class ProductsService {
  constructor(private readonly pricing: PricingService) {}   // NestJS injects it

  priceForCustomer(mrp: number) {
    return this.pricing.withGst(this.pricing.discounted(mrp, 10));
  }
}

src/products/products.module.ts

@Module({
  controllers: [ProductsController],
  providers: [ProductsService, PricingService],   // both must be registered
})
export class ProductsModule {}

How NestJS Knows the Type

With emitDecoratorMetadata, the TypeScript compiler writes the constructor parameter types into the compiled JavaScript (design:paramtypes). NestJS reads that list with reflect-metadata and looks up each class in the module.

// roughly what tsc emits for ProductsService
ProductsService = __decorate([
    Injectable(),
    __metadata("design:paramtypes", [PricingService])
], ProductsService);

Note: This is why you inject classes, not interfaces: interfaces disappear after compilation, so there is nothing to look up. For interfaces use an injection token (next module).