Injection token in angular
While working in angular many developers rarely create their own injection token. I think this is because, to use an injection token we have to use the @Inject decorator and it looks like some boilerplate has been added to our code. In many scenarios, we can totally skip creating our own injection tokens by using services. This can fulfill our requirements many times however there are some use cases where we have to use our own injection token. Following are some of them
- For types such as interface, generic types & callback types.
- For differentiating between two or more similar types.
- As default providers.
For interface and callback types
At line 20 we are injecting an array of type Todo
. If we do not use TODO_LIST
injection token, then we will get an error No subtable injection token for param 'myTodos'
. It is because interfaces are not available in javascript and Todo
type can not be resolved at runtime.
The same error can be seen in the case of callback type AtoBConverter
as we have seen for interfaces. By looking at the above examples we can say that if we are using any type with dependency injection, which is not supported by javascript, we should use our own Injection token for that type.
For differentiating between two or more similar types
Let’s consider a scenario where we want two separate lists of pending
and done
Todos. The type for both will be an array of type Todo
. So the question that arises is how can we differentiate between these two lists while injecting them into our component. Let’s see the below example.
Here we have created PENDING_TODOS
and DONE_TODOS
injection token for differentiating between these two similar types and we have also created two providers, pendingTodosProvider
& doneTodosProvider
, for giving us the expected list of todos in our component.
As default providers
In some scenarios, a developer might forget to configure a provider for an injection token. In that case, we will get an error NullInjectorError
. We can avoid this error by providing a default value for that particular injection token. This can be done by passing an object of option as the second parameter into the InjectionToken
constructor. In this object, we can assign a factory function that will return a default value, if no injector is found for our injection token. Let’s have a look at the below example.
Here we have not configured any provider for TODO_LIST
token. Therefor at line number 11, an empty array will be assigned to todos
instead of throwing NullInjectorError
. This empty array is returned by factory
method defined at line number 4.
Instead of using default providers, we can use @Optional
decorator while injecting TODO_LIST
token and null
will be assigned to todos
. The problem with this approach is that if we will try to access array function such as foreach, reduce then we will get error and this might break our code.
Apart from above all use cases, there is one more benefit of using injection token. It makes our code more tree-shakable. Instead of creating a service with many helper functions, we should create create injection token for each helper function. This way if we are not using any help function in our code then it will not be included in the dist bundle.
That’s all for this article. If you like, please hit clap, or if you have some feedback to give, please comment.