I have been refactoring an Angular project of mine to use TypeScript. I have been doing this for a few reasons:
- To be able to start using the ECMAScript 6 and beyond coding features.
- To make it easier to upgrade to Angular 2 in the future.
- To take advantage of TypeScrip’s typing and other features.
One of the issues I have come across while doing this exercise is that all my services are actually Angular Factories.
Angular has three types of services you can have to reuse logic across your application and they are services, factories, and providers.
Factories are typically the most common way to create these components. A factory is basically a function call that returns an object, and that object contains properties and functions.
Services are similar to factories except that they are instantiated when you call them. So the functionality you want to reuse, you would put the logic on the “this” keyword which is essentially attaching the functionality to the service itself.
When you use a service Angular will automatically call it using the “new” keyword.
Providers are a little more involved, but they are useful when you want to setup some configuration before before you actually call it. It is the only type of service that is available in the “config” section of a module which is executed first, so you can configure it and then call it later in a controller for example.
So in the code above. The greeting is being set in the configuration section which is called as soon as the module is loaded up. Then later, once the controller starts executing it’s code, the service is called returning the name that was setup in the configuration section earlier.
The problem in TypeScript
Because in TypeScript you create interfaces and then classes that implement those interfaces, factories will not new up your class. So the following will not work in TypeScript.
In the above code, the factory call out to Foo does not instantiate the Foo class, so it is returned as an empty object.
To get around this issue, I had to “new up”, instantiate the classes myself before I returned them as a factory.
Now my factory service point to my “instantiator” function which in turn, returns an instantiated Foo object.
So the lesson learned is: if you are going to use TypeScript with Angular (v1), you might as well start using services rather than factories as this will save you a step, but if you are going to use factories, remember to instantiate them first before you inject them into your code.