In July 2015, Microsoft announced the release of Typescript 1.5, introducing decorators, based on the ES7 decorator proposal. I had to test it!
It should be noted that decorators are still in stage 1 proposal and their actual implementation could change anytime
This article will demonstrate the possibility of using decorators to do dependency injection in Typescript.
Why use injection?
-
Injection avoids the pollution of the global namespace with object instances.
-
It provides an easy way to share an object instance across our application, without the need to pass the object everywhere.
In our constantly growing Single Page Application, we have some objects that are constants through a user visit. E.g., the visitor’s browser and the logged User. The first offers us some utility methods like
browser.isMobile()
orbrowser.isIE()
. The second which contains a set of permissions, email, etc., is used, among other things, to determine which panels the user can access. -
The injected object is always up-to-date.
We use Backbone to periodically refresh our models with the state from the server. Our injector allows us to create the instance once and use it where we need it.
Implementation
I made a simple project on GitHub that provides the Injector and decorator. Feel free to contribute!
It’s also available on npm: npm install dose
.
It uses a small registry that stores values in a map. There’s a lot to improve in there, but it met my requirements.
The Injector can now be used like this:
It works and it’s far from magic. We must cast the registered value in User
because getRegistered
returns an object of type any
.
Enters the decorator
First, let’s look at the simpler injector:
In this code, target
is the object instance on which we want to inject and key
is the property. Let’s see the usage:
target => UserConsumer
property => user
keys[0] => ‘user’
The injectorMethod
does about the same but accept 1…N keys instead of one.
Note that it adds parameters to the methods. I have yet to make it work directly in the method parameters
Nice! But we can do better. We don’t want to have a decorator for the method and another for the property. Let’s wrap them with a small function that detects the type, so we can use @inject('key')
on both methods and parameters
Here’s the complete UserConsumer code. A small demo project is available on GitHub.
The official Typescript decorator page has a lot more information on what is possible with the decorators.
Try it
Create a npm projet that depends on dose & Typescript >= 1.5. Then you can run npm install
to download the dependencies.
Import the injector & the inject decorator and you are all set!
Be sure to pass the –experimentalDecorators
flag to your typescript compiler
That’s it!