You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TSyringe如何注入所有实现某接口或继承抽象类的类实例?

TSyringe 注入同接口所有实现类实例实现方案

你的需求完全可以实现,效果和Spring中@Autowired注入同类型Bean集合的能力一致。

前置注意点

  • TypeScript 接口仅存在于编译阶段,编译后会被完全擦除,因此不能直接用接口作为依赖注入的Token,需要使用字符串、Symbol或者抽象类作为Token载体。
  • @injectable() 装饰器不能修饰接口,仅能修饰实际存在的类,你示例中给接口加@injectable()是无效写法。
  • 你示例中的console.out属于笔误,正确API是console.log。

实现步骤

1. 定义接口与统一Token

import { injectable, inject, container } from "tsyringe";

// 定义统一的注入Token,避免硬编码字符串冲突
export const I_SERVICE_TOKEN = Symbol("IService");

// 接口无需加@injectable
export interface IService {
    foo(): void;
}

2. 编写接口实现类

@injectable()
export class Service1 implements IService {
    foo() { console.log("bar"); }
}

@injectable()
export class Service2 implements IService {
    foo() { console.log("baz"); }
}

3. 容器中注册同Token多实现

TSyringe 支持对同一个Token多次注册不同的实现,解析时会自动返回所有实现的实例数组:

// 多次注册同一个Token,绑定不同实现类
container.register(I_SERVICE_TOKEN, { useClass: Service1 });
container.register(I_SERVICE_TOKEN, { useClass: Service2 });

4. 注入使用

@injectable()
export class CollectorService {
    constructor(
        @inject(I_SERVICE_TOKEN)
        private services: IService[]
    ) {
        // 遍历调用所有实现
        services.forEach(s => s.foo());
    }
}

抽象类简化方案(可选)

如果你不想单独维护Token,可以直接用抽象类替代接口,抽象类编译后是真实存在的构造函数,可以直接作为Token使用:

// 抽象类直接作为Token
@injectable()
export abstract class AbsService {
    abstract foo(): void;
}

// 注册时直接用抽象类当Token
container.register(AbsService, { useClass: Service1 });
container.register(AbsService, { useClass: Service2 });

// 注入
constructor(@inject(AbsService) private services: AbsService[]) {}

内容的提问来源于stack exchange,提问作者Aníbal Deboni Neto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 03:27:03