JavaScript
AdventCalendar
TypeScript
knockoutjs

Knockout.js を TypeScript で書いてみる

More than 3 years have passed since last update.

これは TypeScript Advent Calendar 2014 の11日目(12/11)の投稿です。

TypeScirpt、これは単純に優れているのではと思い、この機に試してみました。今回は薄いフレームワーク(ライブラリ)として私が勝手に重宝している Knockout.js に TypeScript を適用してみます。

尚、事前準備となる周辺環境(WebStorm、TypeScript本体、TSD)については昨日こちらに書いたので、宜しければ参照ください。

WebStorm で TypeScript を始めよう!


まずは Knockout.js の環境構築

Yeoman でサクりと作っちゃいます。


今回の前提環境


yo:1.3.2

generator-webapp:0.5.1

Knockout.js:3.2.0

jQuery:2.1.1



手順

Yeoman の generator-webapp を起動し、適当に Bootstrap のみを選択します(まあ何でもいいのですが)。

$ yo webapp

次に、Bower で Knockout.js をインストールします。

$ bower install knockoutjs --save

このバージョンのジェネレータで作成されるプロジェクトでは、次のコマンドで index.html に必要なものが自動で追記されるので、コマンドを叩きます。

$ grunt wiredep

結果的に、次のように追記されました。jQuery も入っていますね。


index.html

<!-- build:js(.) scripts/vendor.js -->

<!-- bower:js -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/knockoutjs/dist/knockout.js"></script>
<!-- endbower -->
<!-- endbuild -->

まずはこの状態(TypeScriptを導入しない状態)で、Knockout.js の動作確認をしてみます。View を次のように書き、


app/index.html

<p>名:<input data-bind="value: firstName, valueUpdate: 'afterkeydown'"></p>

<p>姓:<input data-bind="value: lastName, valueUpdate: 'afterkeydown'"></p>
<h4>フルネームは <span data-bind="text: fullName"> </span></h4>

ViewModel を次のように書きます。


app/scripts/main.js

$(function() {

var ViewModel = function(first, last) {
this.firstName = ko.observable(first);
this.lastName = ko.observable(last);

this.fullName = ko.computed(function() {
return this.lastName() + " " + this.firstName();
}, this);
};

ko.applyBindings(new ViewModel("太郎", "山田"));
});


$ grunt serve でブラウザを開き、データバインドが動いていればOKです。


型定義ファイルの導入

昨日の投稿(WebStorm で TypeScript を始めよう!)にも書きましたが、このプロジェクトに jQuery と Knockout.js の型定義ファイルをインストールします。

$ tsd init

$ tsd query jquery knockout --action install --resolve --save

以降は TypeScript ファイルの冒頭で、次のように型定義ファイルを指定すればOKです。

/// <reference path="../../typings/tsd.d.ts" />


Knockout.js を TypeScript で書いてみる

いったん、元の app/scripts/main.js は削除し、app/scripts/main.ts を作成します。WebStorm のウオッチャーにも追加しておきます。

ここまでで、プロジェクトは次のようになっているハズです。

スクリーンショット 2014-12-09 19.07.38.png


View を書きます

こちらは普通に。


app/index.html

<p>名前:<input data-bind="value: name, valueUpdate: 'afterkeydown'"></p>

<p>年齢:<input data-bind="value: age, valueUpdate: 'afterkeydown'"></p>
<p>あなたは <span data-bind="text: name"></span> さん、<span data-bind="text: age"></span> 歳 ですね!</p>


ViewModel を書きます

あまり TypeScript 分かってないので.. それっぽく書きます。name は文字列型(string)、age は数値型(number) という風に型を定義しました。


app/scripts/main.ts

/// <reference path="../../typings/tsd.d.ts" />

class HogeViewModel {
// 何も指定しないと public になる
private name: KnockoutObservable<string> = ko.observable('');
private age: KnockoutObservable<number> = ko.observable(0);

constructor(name: string, age: number) {
this.name(name);
this.age(age);
}
}

$(function() {
ko.applyBindings(new HogeViewModel('山田', 32));
});


コンソールで $ grunt serve し動作確認します。

スクリーンショット 2014-12-09 19.19.53.png


型チェックやコード補完の具合を見てみる

※ 上にも書きましたが、IDE は WebStorm を使っています。

Knockout.js のコード補完が効いています。

4.png

7.png

もちろん、TypeScript のコード補完も効きます。

6.png

型エラーは、リアルタイムにチェックされます。

b87696ed-a096-718d-96cb-bb01b04cb4f4.png

3cfc22b2-e6ea-b294-a948-111846aa6853.png

ちなみに型定義ファイルを指定しないと、こんな感じでエラーになります。

5.png


コンパイル後の .js ファイルを見てみる

こんな感じで変換されています。綺麗に読める感じ。


ちなみに型チェックがある JavaScript コードが吐かれるわけではないです。


1.png


おわりに

まだ導入の域を出ないですが、Knockout.js を TypeScript で書く手順を紹介しました。

TypeScript の静的な型システムは強力なので、これから自分的に試していきたいな、と思っています。

今回のソースはこちらに置きました。

https://github.com/hkusu/Knockout.js_TypeScript_sample

.jsファイルや型定義ファイルはもしかして commit しない流儀なんだろうか? よくわからず。)