typescripttsyringe

TSyringe inject all classes that implements some interface


I've been looking if it's possible for TSyringe to inject all classes that implements some interface (or extends from an abstract class), like this:

@injectable()
export interface IService {
    foo(): void;
}

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

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

export class CollectorService {
    constructor(
        @inject('Service')
        services: IService[]
    ) {
        services.forEach(s => s.foo());
    }
}

I just started using TSyringe a month ago, so I'm not familiar with all features and I don't know how to register this kind of dependency (if it's possible to achieve what I'm proposing) in the DI container. I'm trying to mimic Spring @Autowire annotation.


Solution

  • I couldn't get the registry per class to work as in Aníbal Deboni Neto asnwer, but using an proxy class to place all the registries worked for me. I also used a Symbol so that I don't have any magic strings.

    interface IBar {}
    
    @injectable()
    class Foo implements IBar {}
    @injectable()
    class Baz implements IBar {}
    
    @registry([
      {token: Bar.token, useToken: Foo},
      {token: Bar.token, useToken: Baz}
    ])
    abstract class Bar {
      static readonly token = Symbol("IBar");
    }
    
    @injectable()
    class User{
      constructor(@injectAll(Bar.token) private bars: IBar[]) {
      }
    }
    
    const bars: IBar[] = container.resolveAll<IBar>(Bar.token);
    const user: User = container.resolve(User);
    
    

    Source: https://github.com/microsoft/tsyringe#register