The main advantage of using es-injection is that components may be injected into other components.
This helps properly separating the responsibilities of each components, while making testing more straightforward as injected dependencies can simply be mocked.
Injecting a dependency is done using the @Inject
decorator.
A number of additional decorators also make it possible to further refine what gets injected.
Since es-injection manages the instantiation of components, it needs to be able to provide all constructor arguments.
In practice, it means all constructor parameters come from injection without requiring the @Inject
decorator.
@Component
class MyComponent {
constructor(dependency1: DependencyComponent, dependency2: OtherDependencyComponent) {
}
}
While convenient, constructor-based injection should be limited to dependencies that are necessary to the instance construction.
When that is not the case, method-based injection should be favored.
Method-based injection tells es-injection to inject a dependency via a method call.
For such cases, the @Inject
decorator is required.
@Component
class MyComponent {
@Inject
setDependencies(dependency1: DependencyComponent, dependency2: OtherDependencyComponent): void {
}
@Inject
setMoreDependencies(dependency3: YetAnotherDependencyComponent): void {
}
}
Multiple methods can be decorated with @Inject
, but common practice involves injecting a single dependency per method
call though.
Property-based injection tells es-injection to inject a dependency directly into a property.
Doing this required the @Inject
decorator as well.
@Component
class MyComponent {
@Inject
dependency1: DependencyComponent;
@Inject
dependency2: OtherDependencyComponent;
}
While convenient, property-based injection can prove difficult to work with as such injected properties are generally meant to be private and could therefore not be set from outside the class, e.g. for tests.
TODO.
An optional dependency is a dependency that may not be available within the application context.
When encountering such an optional dependency, the injected value will be undefined
if the dependency is unavailable.
@Component
class MyComponent {
@Inject
setDependency(@Optional dependency: DependencyComponent|undefined): void {
}
}
Sometimes multiple classes match an injection request, such as injecting a based class that has multiple derived components.
In that case, an array or a map can be used to inject all available components.
Due to current limitations with the code emitted from a TypeScript compilation, es-injection cannot know the type to inject when using arrays or maps.
To work around this issue, the @ElementClass
decorator must be used.
When injecting an array, the @ElementClass
decorator hints at the type of the elements in the list.
@Component
class MyComponent {
@Inject
setDependencies(@ElementClass(BaseClass) dependencies: Array<BaseClass>): void {
}
}
When injecting a map, the @ElementClass
decorator hints at the type of the values in the list.
The keys must always be strings, and will be each component's name.
@Component
class MyComponent {
@Inject
setDependencies(@ElementClass(BaseClass) dependencies: Map<string, BaseClass>): void {
}
}