TypeScriptでカスタムdirectiveのpre/postLinkの書き方

# 最初に
世間はAngular2で盛り上がっているのにlinkの話かーいって感じですが、directive内でDOM操作したい、jQuery使いたいとかまだニーズあるよね、ということで実装してみました。

調べ方も含めてご参考までに…。

やりたいことは、[AngularJS Directiveの処理順を網羅してみた:処理中にjQueryで要素を追加したらどーなるの](http://qiita.com/armorik83/items/38fe685cc76163c7e8ce#%E5%87%A6%E7%90%86%E4%B8%AD%E3%81%ABjquery%E3%81%A7%E8%A6%81%E7%B4%A0%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%97%E3%81%9F%E3%82%89%E3%81%A9%E3%83%BC%E3%81%AA%E3%82%8B%E3%81%AE)の、k-cパターンです。

> k-c: pre-link内でjQuery#append()


# version

- Angular 1.5
- TypeScript 1.8

# 定義ファイルを読む

## interface IDirective
```ts:angular.d.ts
interface IDirective {
    compile?: IDirectiveCompileFn;
    controller?: any;
    controllerAs?: string;
    /**
     * @deprecated
     * Deprecation warning: although bindings for non-ES6 class controllers are currently bound to this before
     * the controller constructor is called, this use is now deprecated. Please place initialization code that
     * relies upon bindings inside a $onInit method on the controller, instead.
     */
    bindToController?: boolean | Object;
    link?: IDirectiveLinkFn | IDirectivePrePost;
    multiElement?: boolean;
    name?: string;
    priority?: number;
    /**
     * @deprecated
     */
    replace?: boolean;
    require?: string | string[] | {[controller: string]: string};
    restrict?: string;
    scope?: boolean | Object;
    template?: string | Function;
    templateNamespace?: string;
    templateUrl?: string | Function;
    terminal?: boolean;
    transclude?: boolean | string | {[slot: string]: string};
}
```
`link?: IDirectiveLinkFn | IDirectivePrePost;`となっているので、linkにはIDirectiveLinkFn かIDirectivePrePostのInterfaceを使えばいいみたいです。

## interface IDirectiveLinkFn / IDirectivePrePost 

```ts:angular.d.ts
interface IDirectiveLinkFn {
    (
        scope: IScope,
        instanceElement: IAugmentedJQuery,
        instanceAttributes: IAttributes,
        controller: {},
        transclude: ITranscludeFunction
    ): void;
}

interface IDirectivePrePost {
    pre?: IDirectiveLinkFn;
    post?: IDirectiveLinkFn;
}
```
IDirectivePrePostでpre/postにそれぞれIDirectiveLinkFnを継承していますね。
というわけで、IDirectiveを継承したカスタムdirectiveにIDirectivePrePostを継承させたlinkを作成しましょう。

## 蛇足：interface IDirectiveCompileFn

```ts:angular.d.ts
interface IDirectiveCompileFn {
        (
            templateElement: IAugmentedJQuery,
            templateAttributes: IAttributes,
            /**
             * @deprecated
             * Note: The transclude function that is passed to the compile function is deprecated,
             * as it e.g. does not know about the right outer scope. Please use the transclude function
             * that is passed to the link function instead.
             */
            transclude: ITranscludeFunction
        ): IDirectivePrePost;
    }
```
IDirectiveCompileFnはIDirectivePrePostを返しています。


# 書いてみた
```ts:myDirective.ts
module myDirectivesModule {

    export class myDirective implements ng.IDirective{
        // TODO IDirectiveを参考に必要なものを定義
        // public restrict: string;
        // public …

        constructor() {
           this.init();
        }

        public static Factory(): ng.IDirectiveFactory {
            "ngInject";
            var directive = () => {
                return new myDirective();
            }
            return directive;
        }

        // ここ！！
        public link: ng.IDirectivePrePost = {
            pre: ($scope: ng.IScope, $element: ng.IAugmentedJQuery, $attrs: ng.IAttributes): void => {
                // prelinkで実行したい処理
            },
            post: ($scope: ng.IScope, $element: ng.IAugmentedJQuery, $attrs: ng.IAttributes): void => {
                // postlinkで実行したい処理
            }
        }

        private init() {
            // TODO 初期化
            // this.restrict = 'E';
            // this.…
        }
    }   
}

var myapp = angular.module("app"); //ng-app="app"
"ngInject";
myapp.directive('myCustomDirective', myDirectivesModule.myDirective.Factory());
```

```html:sample.html
<html lang="ja" ng-app="app">
//・・・
　<my-custom-directive></my-custom-directive>
//・・・
</html>
```

- "ngInject";：gulp-ng-annotate用の定義です。

# 感想
TypeScriptは定義ファイルみたら何とかなるー…かもヽ( ´ ∇ ｀ )ノ