Back to Blog
Dependency InjectionTypeScriptTestingArchitecture

Dependency Injection in TypeScript Applications

Implement dependency injection for testable code. Learn DI patterns, containers, and testing strategies.

B
Bootspring Team
Engineering
February 27, 2026
2 min read

Dependency injection improves testability and flexibility.

The Problem#

1// ❌ Hard to test 2class UserService { 3 private db = new PostgresDatabase(); 4 5 async createUser(data) { 6 return this.db.users.create(data); 7 } 8}

Constructor Injection#

1// ✅ Dependencies injected 2interface Database { 3 users: UserRepository; 4} 5 6class UserService { 7 constructor(private database: Database) {} 8 9 async createUser(data) { 10 return this.database.users.create(data); 11 } 12} 13 14// Production 15const service = new UserService(new PostgresDatabase()); 16 17// Testing 18const mockDb = { users: { create: jest.fn() } }; 19const testService = new UserService(mockDb);

Factory Functions#

1function createUserService(deps: { db: Database; email: EmailService }) { 2 return { 3 async createUser(data) { 4 const user = await deps.db.users.create(data); 5 await deps.email.sendWelcome(user.email); 6 return user; 7 }, 8 }; 9}

Composition Root#

1// composition-root.ts 2export function createApp() { 3 const database = new PostgresDatabase(); 4 const emailService = new SendGridService(); 5 6 const userService = new UserService(database, emailService); 7 const userController = new UserController(userService); 8 9 return createRouter({ userController }); 10}

Testing with DI#

1describe('UserService', () => { 2 let service: UserService; 3 let mockDb: jest.Mocked<Database>; 4 5 beforeEach(() => { 6 mockDb = { users: { create: jest.fn() } } as any; 7 service = new UserService(mockDb); 8 }); 9 10 it('should create user', async () => { 11 mockDb.users.create.mockResolvedValue({ id: '1' }); 12 const result = await service.createUser({ email: 'test@test.com' }); 13 expect(result.id).toBe('1'); 14 }); 15});

Depend on abstractions, keep composition at top level, and inject interfaces not classes.

Share this article

Help spread the word about Bootspring