typescriptdependency-injectiontsyringe

tsyringe - specify which arguments to inject


I am using tsyringe to manage my dependency injection. The following code fragment works.

import 'reflect-metadata'
import {autoInjectable,singleton} from 'tsyringe'

interface sheepProps {
    legCount: number
}

@singleton()
export class Animal {
  makeSound (sound: string) {
    console.log(sound)
  }
}


@autoInjectable()
class Sheep {

  constructor(sheepProps?: sheepProps, private animal?:Animal) {}

  beeeeh () {
    this.animal.makeSound('bleeeeh')
  }
}

const props: sheepProps = {
    legCount: 4
} 

const sheep = new Sheep(props);
sheep.beeeeh();

However when sheepProps is not provided in the call to the constructor by changing new Sheep(props) to new Sheep(), an error is thrown:

Error: Cannot inject the dependency "sheepProps" at position #0 of "Sheep" constructor. Reason: TypeInfo not known for "Object"

To me is seems like tsyringe is trying to inject something when sheepProps is not provided in the call to the constructor.

Is this assumption correct, and how would I fix this so I can still use optional arguments in a constructor?


Solution

  • The below code solves the problem, in a way that it is still possible to use new to instantiate a class.

    Note: Please be aware that when sheepProps is not given to the constructor, the value will be an empty object in this case. It is possible to set an other default, however you cannot set it to undefined!

    import 'reflect-metadata'
    import {autoInjectable,singleton, inject, container} from 'tsyringe'
    
    interface SheepProps {
        legCount: number
    }
    
    @singleton()
    export class Animal {
      makeSound (sound: string) {
        console.log(sound)
      }
    }
    
    const sheepPropsToken = Symbol();
    container.register(sheepPropsToken, {useValue: {} });
    
    @autoInjectable()
    class Sheep {
        private props: SheepProps
    
      constructor(@inject(sheepPropsToken) sheepProps?: SheepProps, private animal?:Animal) {
        console.log(sheepProps)
        this.props = sheepProps
      }
    
      beeeeh () {
        this.animal.makeSound('bleeeeh')
      }
    
      getLegCount() {
        if(this.props.legCount !== undefined) {
            console.log(this.props.legCount)
        } else {
            console.log('Not known to have legs.')
        }
      }
    }
    
    const props: SheepProps = {
        legCount: 4
    } 
    
    const sheep1 = new Sheep();
    sheep1.beeeeh();
    sheep1.getLegCount();
    
    const sheep2 = new Sheep(props);
    sheep2.beeeeh();
    sheep2.getLegCount();
    

    Output:

    {}
    bleeeeh
    Not known to have legs.
    { legCount: 4 }
    bleeeeh
    4