Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inject Dependencies into Static Factory in Typescript

I have a service written in typescript as a Class. In this class I define a static Factory which I inject dependencies.

When I compress my application, the dependencies are being compressed and I receive an undefined provider error.

Here is my service:

export class TInterceptor {    
public static $inject = ['$q', '$rootScope'];
public static Factory($q:ng.IQService, $rootScope:ng.IRootScopeService)
{
  return new TInterceptor($q, $rootScope);
}
constructor(private $q:ng.IQService, private $rootScope:ng.IRootScopeService){}...}

Service being called here:

  angular
    .module('t')
    .config(config);

  function config($httpProvider:ng.IHttpProvider)
  {
    $httpProvider.interceptors.push(TInterceptor.Factory);
  }

My question is, how to I make sure the dependencies are protected from being overwritten when I compress my code?

like image 274
tgrux Avatar asked Nov 01 '22 02:11

tgrux


2 Answers

Register the factory. i.e,

angular.module('myapp').factory('interceptorFactory', ['$q','$rootScope',TInterceptor.Factory]);

and in the config block provide factory name:

$httpProvider.interceptors.push('interceptorFactory');

Or supply array as well (guess it should work as well as it internally uses $injector.invoke it is not a string)

 $httpProvider.interceptors.push(['$q','$rootScope', TInterceptor.Factory]);

You forgot explicit annotation on the config block as well.

.config(['$httpProvider', config]);
like image 150
PSL Avatar answered Nov 15 '22 05:11

PSL


EDIT: Update for Typescript 1.6

Now that Typescript 1.6 is out, with support of class expressions, you can use directly a class expression with a closure to use your injections:

angular.module('myApp')
    .factory('MyFactory', function($q, $http) {

        return class {

            constructor(data) {
                // Here you have access to $q and $http
            }
        }
    })

Typescript 1.5

Typescript not allowing class expressions at the moment until version 1.6, I personally use this syntax for now:

class MyClass {

    constructor(
        private $q: ng.IQService,
        private $http: ng.IHttpService
        data) {

    }
}

Then I use the standard Angular factory definition that permits to use ng-annotate during the build, and I currify the class with factory injections before returning it:

angular.module('myApp')
    .factory('MyFactory', function($q, $http) {

        var factory = MyClass

        // Return curried MyClass
        return Function.prototype.bind.apply(factory,
            Array.prototype.concat.apply([factory], arguments))
    });

The return line is equivalent to:

return MyClass.bind(MyClass, $q, $http)

It's less readable, but will prevent you from writing two times your dependencies each time you'll change them.

Or if you have Lodash or Underscore, you can do it in a more elegant way:

return _.curry(MyClass).apply(this, arguments)

I'm then able to instantiate my class only by providing essential data:

new MyFactory(data)
like image 42
kube Avatar answered Nov 15 '22 06:11

kube