angularjstypescriptminifyangularjs-controllergrunt-contrib-uglify

Controller inheritance in Typescript with minification causing Error: $injector:unpr Unknown Provider


UPDATE 2019/07/16

My issue is actually caused by the inappropriate use of $inject. I used it as private $inject in api-service.ts but it should be public static $inject = [...]. When uglifying, it relies on the explicit injection but private $inject made it implicit


I have a very much the same issue with this post. Instead of the tProvider unknown, my error message has the specific provider name but look like

Unknown provider: eProvider <- e <- api-service <- baseDI-service

where api-service and baseDI-service are named and registered services for the same module.

My module looks like as below:

module
--api-service
--other-services
--baseDI-service
--componentA
----controllerA extends BaseController
--componentB
----controllerB extends BaseController

I import api-service and other services in baseDI-service which I used as a service container because I don't want to pass a lot parameters in super() of componentA, for example.

So in componentA it looks like:

...
class ComponentAController extends BaseController {
    public static $inject = ['baseDI-service', ...];

    constructor(baseDIService: BaseDIService) {
        ...
        super(baseDIService); 
        ...
    }
}

BaseDIService.ts:

export default class BaseControllerDIService {
    public static $inject = ['api-service', '$http', ...];
    constructor(
        private apiSvc: ApiService,
        private $http: ng.IHttpService,
        ...
    ) {}

    public getBaseClassDependencies() {
        return{
            apiService: this.apiSvc,
            $http : this.$http
            ... : ...
        };
    }
}

BaseController.ts

export default class BaseController implements ng.IComponentController {    
    apiService: ApiService;
    $http: ng.IHttpService;

    constructor(
        baseDIService: BaseDIService
    ) {
        const services = baseDIService.getBaseClassDependencies();
        this.$http = services.$http;        
        this.apiSvc = services.apiService;
        ...
        this.otherService = services.otherServices;
        ...
    }

After Grunt Uglify minification, the error was like Unknown provider: serviceAProvider <- serviceA. Without minification, everything alright.

Prior to this way, I also tried using $injector the same way as baseDI-service in controllerA to pass it to super(), and in BaseController I use $injector.get('api-service'), I got the same issue with minification only.

Could anyone tell why both way I tried failed in Uglify minified mode, and how can sort it out? I do need minification by the way.

Also, is it a good practice using controller inheritance for AngularJS?


Solution

  • To help you find this kind of problem before you uglify, use Strict Dependency Injection.

    From the Docs:

    Using Strict Dependency Injection

    You can add an ng-strict-di directive on the same element as ng-app to opt into strict DI mode:

    <!doctype html>
    <html ng-app="myApp" ng-strict-di>
    <body>
      I can add: {{ 1 + 2 }}.
      <script src="angular.js"></script>
    </body>
    </html>
    

    Strict mode throws an error whenever a service tries to use implicit annotations.

    For more information, see