TypeScript中的依赖注入:完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

TypeScript 中的依赖注入简介



依赖注入 (Dependency Injection, DI) 是一种关键的设计模式,它允许您创建松耦合、可测试且易于维护的应用程序。在 TypeScript 的上下文中,得益于强类型和装饰器的支持,实现 DI 变得特别优雅且安全。



在本文中,我们将探讨什么是依赖注入,如何在 TypeScript 中实现它,以及哪些工具可以简化这个过程。您将了解 DI 如何帮助消除类之间的硬编码耦合,并使您的代码更加灵活。



什么是依赖注入以及为什么需要它?



依赖注入 (Dependency Injection) 是一种模式,其中对象从外部获取其依赖项,而不是自己创建它们。这实现了 控制反转 (Inversion of Control, IoC) 原则。



没有 DI 的问题:

class Logger {    log(message: string): void {        console.log(message);    }}

class UserService { private logger: Logger;

constructor() { this.logger = new Logger(); // 硬编码耦合 }

createUser(name: string): void { this.logger.log(`User ${name} created`); }}


在这个例子中,UserService 被硬编码绑定到 Logger 的具体实现。如果我们想将日志记录器替换为文件日志记录器或远程日志记录器,就必须修改 UserService 的代码。



使用 DI 的解决方案:

interface ILogger {    log(message: string): void;}

class ConsoleLogger implements ILogger { log(message: string): void { console.log(message); }}

class FileLogger implements ILogger { log(message: string): void { // 写入文件 }}

class UserService { constructor(private logger: ILogger) {} // 依赖项被注入

createUser(name: string): void { this.logger.log(`User ${name} created`); }}

// 使用const service = new UserService(new ConsoleLogger());


DI 的优势:

  • 可测试性 — 可以轻松地将真实依赖项替换为模拟对象 (mock objects)。
  • 灵活性 — 可以在不修改类代码的情况下更改系统行为。
  • 职责分离 — 类不负责创建自己的依赖项。
  • 可重用性 — 依赖项可以在应用程序的不同部分使用。


在 TypeScript 中手动实现依赖注入



最简单的方法是通过构造函数或属性注入依赖项。TypeScript 凭借其接口和访问修饰符,使这变得非常方便。



通过构造函数注入 (Constructor Injection)

interface IRepository<T> {    getAll(): Promise<T[]>;    getById(id: number): Promise<T | null>;}

class UserRepository implements IRepository<User> { async getAll(): Promise<User[]> { // 与数据库交互的实际逻辑 return []; }

async getById(id: number): Promise<User | null> { return null; }}

class UserController { constructor( private repository: IRepository<User>, private logger: ILogger ) {}

async getUsers(): Promise<User[]> { this.logger.log('正在获取用户...'); return this.repository.getAll(); }}

// 创建依赖图const logger = new ConsoleLogger();const repository = new UserRepository();const controller = new UserController(repository, logger);


通过属性注入 (Property Injection)

class EmailService {    private sender!: ISender;

setSender(sender: ISender): void {

博客

书籍推荐