Recently I started refactoring one of the Angular projects I am working on with TypeScript. Using TypeScript classes to define controllers is very convenient and works well
This article pretty much covers it and the answer from tanguy_k is pretty much verbatim the example given in the article. It also has all the motivation of WHY you would want to write the class this way. Inheritance, type checking and other good things...
http://blog.aaronholmes.net/writing-angularjs-directives-as-typescript-classes/
I prefer to specify a controller
for the directive and solely inject the dependencies there.
With the controller and its interface in place, I strongly type the 4th parameter of the link function to my controller's interface and enjoy utilizing it from there.
Shifting the dependency concern from the link part to the directive's controller allows me to benefit from TypeScript for the controller while I can keep my directive definition function short and simple (unlike the directive class approach which requires specifying and implementing a static factory method for the directive):
module app {
"use strict";
interface IMyDirectiveController {
// specify exposed controller methods and properties here
getUrl(): string;
}
class MyDirectiveController implements IMyDirectiveController {
static $inject = ['$location', 'toaster'];
constructor(private $location: ng.ILocationService, private toaster: ToasterService) {
// $location and toaster are now properties of the controller
}
getUrl(): string {
return this.$location.url(); // utilize $location to retrieve the URL
}
}
function myDirective(): ng.IDirective {
return {
restrict: 'A',
require: 'ngModel',
templateUrl: 'myDirective.html',
replace: true,
controller: MyDirectiveController,
controllerAs: 'vm',
link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attributes: ng.IAttributes, controller: IMyDirectiveController): void => {
let url = controller.getUrl();
element.text('Current URL: ' + url);
}
};
}
angular.module('myApp').
directive('myDirective', myDirective);
}
All options in answers gave me an idea that 2 entities(ng.IDirective and Controller) are too much to describe a component. So I've created a simple wrapper prototype which allows to merge them. Here is a gist with the prototype https://gist.github.com/b1ff/4621c20e5ea705a0f788.