Files
agent-skills/skills/nestjs-best-practices/rules/di-prefer-constructor-injection.md
Jason Woltje 861b28b965 feat: Expand fleet to 23 skills across all domains
New skills (14):
- nestjs-best-practices: 40 priority-ranked rules (kadajett)
- fastapi: Pydantic v2, async SQLAlchemy, JWT auth (jezweb)
- architecture-patterns: Clean Architecture, Hexagonal, DDD (wshobson)
- python-performance-optimization: Profiling and optimization (wshobson)
- ai-sdk: Vercel AI SDK streaming and agent patterns (vercel)
- create-agent: Modular agent architecture with OpenRouter (openrouterteam)
- proactive-agent: WAL Protocol, compaction recovery, self-improvement (halthelobster)
- brand-guidelines: Brand identity enforcement (anthropics)
- ui-animation: Motion design with accessibility (mblode)
- marketing-ideas: 139 ideas across 14 categories (coreyhaines31)
- pricing-strategy: SaaS pricing and tier design (coreyhaines31)
- programmatic-seo: SEO at scale with playbooks (coreyhaines31)
- competitor-alternatives: Comparison page architecture (coreyhaines31)
- referral-program: Referral and affiliate programs (coreyhaines31)

README reorganized by domain: Code Quality, Frontend, Backend,
Auth, AI/Agent Building, Marketing, Design, Meta.

Mosaic Stack is not limited to coding — the Orchestrator serves
coding, business, design, marketing, writing, logistics, and analysis.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:22:53 -06:00

2.3 KiB

title, impact, impactDescription, tags
title impact impactDescription tags
Prefer Constructor Injection CRITICAL Required for proper DI and testing dependency-injection, constructor, testing

Prefer Constructor Injection

Always 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.

Incorrect (property injection with hidden dependencies):

// Property injection - avoid unless necessary
@Injectable()
export class UsersService {
  @Inject()
  private userRepo: UserRepository; // Hidden dependency

  @Inject('CONFIG')
  private config: ConfigType; // Also hidden

  async findAll() {
    return this.userRepo.find();
  }
}

// Problems:
// 1. Dependencies not visible in constructor
// 2. Service can be instantiated without dependencies in tests
// 3. TypeScript can't enforce dependency types at instantiation

Correct (constructor injection with explicit dependencies):

// Constructor injection - explicit and testable
@Injectable()
export class UsersService {
  constructor(
    private readonly userRepo: UserRepository,
    @Inject('CONFIG') private readonly config: ConfigType,
  ) {}

  async findAll(): Promise<User[]> {
    return this.userRepo.find();
  }
}

// Testing is straightforward
describe('UsersService', () => {
  let service: UsersService;
  let mockRepo: jest.Mocked<UserRepository>;

  beforeEach(() => {
    mockRepo = {
      find: jest.fn(),
      save: jest.fn(),
    } as any;

    service = new UsersService(mockRepo, { dbUrl: 'test' });
  });

  it('should find all users', async () => {
    mockRepo.find.mockResolvedValue([{ id: '1', name: 'Test' }]);
    const result = await service.findAll();
    expect(result).toHaveLength(1);
  });
});

// Only use property injection for optional dependencies
@Injectable()
export class LoggingService {
  @Optional()
  @Inject('ANALYTICS')
  private analytics?: AnalyticsService;

  log(message: string) {
    console.log(message);
    this.analytics?.track('log', message); // Optional enhancement
  }
}

Reference: NestJS Providers