Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
40 prioritized NestJS best practices across architecture, DI, security, performance, testing, and microservices.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
rules/di-prefer-constructor-injection.md
1---2title: Prefer Constructor Injection3impact: CRITICAL4impactDescription: Required for proper DI and testing5tags: dependency-injection, constructor, testing6---78## Prefer Constructor Injection910Always use constructor injection over property injection. Constructor injection makes dependencies explicit, enables TypeScript type checking, ensures dependencies are available when the class is instantiated, and improves testability. This is required for proper DI, testing, and TypeScript support.1112**Incorrect (property injection with hidden dependencies):**1314```typescript15// Property injection - avoid unless necessary16@Injectable()17export class UsersService {18@Inject()19private userRepo: UserRepository; // Hidden dependency2021@Inject('CONFIG')22private config: ConfigType; // Also hidden2324async findAll() {25return this.userRepo.find();26}27}2829// Problems:30// 1. Dependencies not visible in constructor31// 2. Service can be instantiated without dependencies in tests32// 3. TypeScript can't enforce dependency types at instantiation33```3435**Correct (constructor injection with explicit dependencies):**3637```typescript38// Constructor injection - explicit and testable39@Injectable()40export class UsersService {41constructor(42private readonly userRepo: UserRepository,43@Inject('CONFIG') private readonly config: ConfigType,44) {}4546async findAll(): Promise<User[]> {47return this.userRepo.find();48}49}5051// Testing is straightforward52describe('UsersService', () => {53let service: UsersService;54let mockRepo: jest.Mocked<UserRepository>;5556beforeEach(() => {57mockRepo = {58find: jest.fn(),59save: jest.fn(),60} as any;6162service = new UsersService(mockRepo, { dbUrl: 'test' });63});6465it('should find all users', async () => {66mockRepo.find.mockResolvedValue([{ id: '1', name: 'Test' }]);67const result = await service.findAll();68expect(result).toHaveLength(1);69});70});7172// Only use property injection for optional dependencies73@Injectable()74export class LoggingService {75@Optional()76@Inject('ANALYTICS')77private analytics?: AnalyticsService;7879log(message: string) {80console.log(message);81this.analytics?.track('log', message); // Optional enhancement82}83}84```8586Reference: [NestJS Providers](https://docs.nestjs.com/providers)87