typescriptdependency-injectiontsyringe

TSyringe: How to change a parameter of an injected object?


I have an app with multiple different components, each component having their own dependency and am using TSyringe to manage dependency injection. One of the components is an operator such as this:

// myoperator.ts

@injectable()
export class MyOperator {
    constructor(
        private dependencyA: DependencyA,
        protected dependencyB: DependencyB,
        protected dependencyC: DependencyC,
        protected operationType: string
    ){
         // initialize operator, etc.
    }

    // ...

}

It is a class that does an operation, depends on a bunch of other classes and has a single string parameter that specifies the way it will operate.

In the main application I'm initializing all the different components that the main app uses and I need to initialize MyOperator with several different operation types.

// mainapp.ts

@singleton()
export class MainApp {
    constructor(
        componentA: ComponentA,
        componentB: ComponentB,
        componentC: ComponentC,
        operatorWithOperationTypeFoo: MyOperator // the operationType should be "foo"
        operatorWithOperationTypeBar: MyOperator // the operationType should be "bar"
        operatorWithOperationTypeBaz: MyOperator // the operationType should be "baz"
    ) {
         // initialize main app, etc.        
    }

    public start() {
        // start main app etc.
    
    }
}

// main.ts

const app = container.resolve(MainApp);
app.start();

My question is, how can I change that single operationType parameter in the MyOperator class when defining them in the MainApp constructor parameters?


Solution

  • I eventually realized that the solution is really simple: inheritance.

    I declare my base operator:

    @singleton()
    export class MyOperator {
        constructor(
            private dependencyA: DependencyA,
            protected dependencyB: DependencyB,
            protected dependencyC: DependencyC,
            protected operationType: string
        ){
             // initialize operator, etc.
        }
    
        // ...
    
    }
    

    And then I extend my other operators from this operator, injecting the dependency:

    container.register(CustomType.BAZ, { useValue: CustomType.BAZ });
    
    
    @singleton()
    export class MyOperatorWithOperationTypeBaz extends MyOperator {
        constructor(
            private dependencyA: DependencyA,
            protected dependencyB: DependencyB,
            protected dependencyC: DependencyC,
            @inject(CustomType.BAZ) protected operationType: string
        ){
             super()
             // initialize operator, etc.
        }
    
        // ...
    
    }