简体   繁体   中英

Is it possible to use a constructor function as a type of an argument of another function in TypeScript?

A few days ago I've found a TypeScript language. According to video reviews it looks pretty promising for me as it brings to JavaScript an appropriate code completion, implicit code documentation and, probably, makes it more type safety.

I'm trying to rewrite a simple AngularJS application in TypeScript. I'd like to specify types of parameters, which are injected to controllers. Let's assume the following JS code:

// service.js
angular.module('app').service('MyService', MyService);
function MyService() {
    this.test = function test() { console.log('test'); };
}

// controller.js
angular.module('app').controller('MyController', MyController);
function MyController($scope, MyService) {
    $scope.test = function test() { MyService.test(); };
}

I'm trying to achieve something like this:

// controller.ts
angular.module('app').controller('MyController', MyController);
function MyController($scope, MyService:MyService) {
    // ...
}

So it'd be easier to write code of the controller with code completion for MyService parameter. However, this code makes a compiler to emit error TS2304: Cannot find name 'MyService' .

I've tried a couple to things and found at least 2 possible solutions. However, non of them seems to be ideal.

1) Creation of an additional interface, which declares all methods of the service. But this approach requires a lot of additional typing (actually, we define the same set of methods with full signature twice and also have to update several things in case of changes). This way is totally okay when the interface is implemented multiple times, but looks redundant for a single AngularJS service.

2) Constructor function can be replaced with a class. This way it is possible to use a name of the class as a type of the parameter. However, this also leads to a couple of problems:

  • typescript compiler transforms class definitions into closures which are assigned to variables declared with var keyword (at least, dealing with ES5). This requires the AngularJS service declaration to be placed after the class definition at the very bottom of a file. It increases a possibility to forget to do it.

     angular.module('app').service('MyService', MyService); class MyService { test() { console.log('test'); } } // becomes angular.module('app').service('MyService', MyService); var MyService = (function () { function MyService() { } MyService.prototype.test = function () { console.log('test'); }; return MyService; }()); 
  • going this way, we have to inject dependencies to a constructor function of the service. As a result, it is necessary to specify an excess this. string each time a dependency is used.

So, are there any other ways to pass a constructor function as a type of a parameter of another function? Thanks.

PS: I don't know whether it's necessary or not, but I'm using Sublime Text 3 with an official TypeScipt plugin and gulp-typescript for compilation.

Yes, you can do this. See working CodePen

class MyController
{
  static $inject = ['MyService','$scope'];

  constructor(private myService:MyService, private $scope:any){
    this.$scope.test = this.myService.test;
  }  
}

class MyService{  
  test(){ 
    console.log('test');
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM