TL;DR
- NestJS uses constructor injection. Declare type in constructor → Nest resolves it.
- Register providers in module's
providers array. Export to share across modules.
@Injectable() marks a class as a provider.
Basic Pattern
// service
@Injectable()
export class UsersService {
private users: User[] = [];
findAll(): User[] { return this.users; }
create(dto: CreateUserDto): User { /* ... */ }
}
// controller — just declare in constructor
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get()
findAll() { return this.usersService.findAll(); }
}
// module — register everything
@Module({
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService], // share with other modules
})
export class UsersModule {}
Provider Types
| Type |
Use Case |
Syntax |
| Class |
Standard service |
providers: [MyService] |
| Value |
Config/constants |
{ provide: 'API_KEY', useValue: 'xxx' } |
| Factory |
Dynamic creation |
{ provide: 'DB', useFactory: () => new Db() } |
| Existing |
Alias |
{ provide: 'AliasService', useExisting: RealService } |
Injection Scopes
@Injectable({ scope: Scope.DEFAULT }) // Singleton (default)
@Injectable({ scope: Scope.REQUEST }) // New instance per request
@Injectable({ scope: Scope.TRANSIENT }) // New instance per injection
Custom Injection Token
// token
export const CONFIG = Symbol('CONFIG');
// register
{ provide: CONFIG, useValue: { port: 3000 } }
// inject
constructor(@Inject(CONFIG) private config: AppConfig) {}