AngularJS+TypeScriptを試してみた。

2014/3/2(日) 第7回西区プログラム勉強会
Photo by Web制作向け無料写真素材/ぱくたそ http://www.pakutaso.com
-自己紹介株式会社キャムの江原と申します。
プログラムしてます。
@itokami1123
企業の経営戦略に役立つサービス「CAM MACS」を
AWSにて提供してます。
会社で作る新しいサービスの技術基盤を色々検証してます。
そこでAngularJSの検証をしています。
でも JavaScriptで大規模って言うとこういう印象が…
JavaScript × 大規模 ≒ デスマーチ
そこでTypeScriptは、どうかな?話になりました。
今日は
TypeScriptでAngularJSを書いたときに
どんな感じになるのかを発表したいと思います。
以下機能をTypeScriptで書いてみました。

module
controller
service
directive
1. module
モジュール(名前空間みたいな)の作成、登録、取得を
グローバル空間で行う

// JavaScript例
// module生成 modu1に依存します
angular.module( "app", [ "modu1"]);
// “app”moduleを参照してcontrollerを追加
angular.module( "app").controller( …
TypeScriptでmoduleを書くと…あまり変わらないですね

// TypeScript
// module生成 modu1に依存します
angular.module( "app", [ "modu1"]);
// “app”moduleを参照してcontrollerを追加
angular.module( "app").controller( …
2. controller
ビュー(DOM)に割り当てるコントローラー

// View DOM sample
<div ng-controller="SampleCtr" >
<h1 ng-click="clickEvent()" >{{text}}</h1>
<input type="text" ng-model="text" />
</div>
// JavaScript例
angular.module("app.controller", ["app.service"])
.controller("SampleCtr", function($scope) {
$scope.text = "";
$scope.clickEvent = function(){
$scope.text += " click!! ";
};
});
TypeScriptでクラスぽくControllerを書くと
型定義情報
///<reference path='xxx/typings/angularjs/angular.d.ts' />
module Sample {
継承して作ります
export interface Scope extends ng.IScope {
text: string;
clickEvent: Function;
使用するScopeの型定義
}
export class SampleCtr {
constructor(public $scope: Scope ) {
public付くと インスタンス変数に
this.$scope.text = “"; // 初期化
this.$scope.clickEvent = angular.bind(this, this.click);
}
click() {
this.$scope.text += " click!! ";
}

bindでメソッドと
$scopeを紐づけます

}
}

!
angular.module("app.controller", [])
.controller("SampleCtr", Sample.SampleCtr);

!
angular.module("app", ["app.controller"]);

moduleへの定義は
JSとまったく同じです。
例えばIntelliJで
定義に飛ぶと
こんな感じで見れます。

///<reference path='xxx/typings/angularjs/angular.d.ts' />
module Sample {
export interface Scope extends ng.IScope {
3. service
コントローラーが呼び出す共通ロジック
 注)angularのモジュールではないです。 TypeScriptは名前空間の機能があります。
///<reference path='xxx/typings/angularjs/angular.d.ts' />
module Srv {
!
export class SampleSrv {
!
constructor() {
}
!
addText(text:string):string {
return text + " [add text]";
}
}
angularのモジュールにサービス機能として登録します。
}
!
angular.module("app.service", [])
.service("srv", Srv.SampleSrv);
サービスは各Controllerの共通処理を記述します。
Controllerで使用する為定義を読込!
///<reference path='xxx/typings/angularjs/angular.d.ts' />
///<reference path='../service/SampleSrvModule.ts' />
module Sample {
// ・・・省略・・・
export class SampleCtr {

srv 文字列で登録している
サービスのインスタンスを呼び出し

constructor(public $scope:Scope,public srv: Srv.SampleSrv) {
// ・・・省略・・・
}

srv 文字列で登録している
サービスのインスタンスを呼び出し

click() {
this.$scope.text = this.srv.addText(this.$scope.text);
}
}
}

JSと同じ書き方でcontrollerモジュールに
serviceモジュールを依存させます

!
angular.module("app.controller", ["app.service"])
.controller("SampleCtr", Sample.SampleCtr);

!
angular.module("app", ["app.controller"]);
4. Directive
続いてカスタム属性を書いてみましょう!
DirectiveはDOM操作を担当します。
IDirectiveインターフェースを実装してクラスを作ります。
///<reference path='./libs/typings/angularjs/angular.d.ts' />
!
module MyDirective {
export class NsStyle implements ng.IDirective {
restrict: string = "A";
replace: boolean = false;
scope: any = false;
compile(elem:ng.IAugmentedJQuery, attrs:ng.IAttributes):any {
elem.addClass("nishi");
}
このDirectiveがつけられたタグのclass名に nishi が追加されます
}
}
!
Directiveの定義は オブジェクトなので new します。
!
angular.module("app.directive", [])
.directive("nStyle", () => new MyDirective.NsStyle() );
!
angular.module("app", ["app.controller", "app.directive"]);
まとめ!
まとめ!

学習コスト高め

AngularJSの学習とTypeScriptの学習を同時にすると頭が
混乱します!
うまく書けば保守性が高そう

TypeScriptはJSには無い型が宣言出来る為、IDEの補完や
定義に飛んだりコンパイルエラーに出来たりできます。
懸念も多いですね…
 新規導入するには初期コストがかかりますし
 まだまだノウハウが少ないので
 実案件より先に社内システムとかで
 練習した方が良さそうです…
 でも、もしかしたら一気に流行るかもしれませんので
 良かったら少し味見してみては??
ご清聴ありがとうございました!

AngularJS+TypeScriptを試してみた。