yutaponのブログ

javascript界隈の興味あるネタを備忘録的に残しておく場所

TypeScriptリファレンス読んだ感想

前に書いた記事の続きになります。

TypeScript触ってみた感想 - yutaponのブログ

やっとTypeScript本を一通り読んだ(目を通した)ので、メモ書きをまとめてみる。

大雑把な感想

TypeScriptのことをたくさん書いてあるのは

  • 4章 基礎知識
  • 6章 応用知識

あたりで、かなり読み応えがあります。

私の場合、1回読んだだけだとよくわからないままになりそうなので、ここは何回も読んでおきたい章です。

7章 開発新ツール ではnodebrew, npm, gruntなど、最近のJS開発では定番のツールの使い方が解説されてるので、JSを余り触ったことがなければ先にこの章を読んでおくといい気がします。

8章 開発サンプルでは、TypeScriptを使ってまるばつゲームを一から作ったり、AngularJS+TypeScript、enchant.js+TypeScriptの組み合わせのサンプルが載っています。

まるばつゲームを作る部分が個人的には面白かったです。
仕様を洗い出して、設計して、実装するって流れがわかりやすかった。

メモなど

ここからは読んでてマーカー引いた部分とかを紹介していきます。

自分向けのことなので、需要あるかわからないですが・・。

tslint(構文チェッカー)

構文チェッカーを入れると捗ります。
私は普通のJSを書くときは、SublimeLinterという構文チェッカーを使っています。
Sublime上で保存するごとに警告を出してくれて、これに従うことでコーディングスタイルとかを一定に保っています。

SublimeLinterがTypeScript対応してくれたらいいのですが、まだ対応してないようなのでtslintを入れます。
(※追記:SublimeText2では未対応ですが、SublimeText3で対応できます)

$ npm install -g tslint # tslintインストール
$ tslint # ざっくりとした使い方
usage: /Users/sskyu/.nodebrew/current/bin/tslint

Options:
  -c, --config          configuration file
  -f, --file            file to lint
  -h, --help            display detailed help
  -o, --out             output file
  -r, --rules-dir       rules directory
  -s, --formatters-dir  formatters directory
  -t, --format          output format (prose, json, verbose)  [default: "prose"]
  -v, --version         current version

Missing required arguments: f  # -f オプション使えと言われる

インストール直後に tslint コマンドで構文チェックしようとするとこうなりました。

$ tslint -f hello.ts

fs.js:427
  return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
                 ^
Error: ENOENT, no such file or directory '/Users/sskyu/tslint.json'

ホームディレクトリにtslint.jsonがないと言われています。

設定ファイルを事前に準備する必要があるようです。

tslint を nodebrewかつnpm -gで入れた場合は、tslintを実行したいソースのあるディレクトリに移動して、下のコマンドを実行して下さい。

$ cp ~/.nodebrew/current/lib/node_modules/tslint/docs/sample.tslint.json ./tslint.json

これで先ほどのtslint.jsonが準備できたので、tslintコマンドが通るはずです。

// @file hello.ts

module Greeting {
    export class Hello {
        constructor(private text: string) {
        }

        say(): void {
            console.log(this.text);
        }
    }
}

var hello: Greeting.Hello = new Greeting.Hello("Hello, world!");
hello.say();

試しに上記のファイルにtslintを実行すると

$ tslint -f hello.ts
hello.ts[15, 13]: file should end with a newline
hello.ts[3, 1]: missing 'use strict'
  • ファイルの最後に空行を追加して
  • 3行目に 'use strict' 記述して

と言ってきます。

コンパイルは通るので、間違ったコードではないのですが、
チーム内でコーディングスタイルを統一するためにも構文チェッカーには従っておくと良いと思います。
(気に入らない警告はtslint.jsonをいじって好みの設定に変えるのもあり)

tsd(型定義ファイルのパッケージマネージャー )

既存のライブラリをTypeScriptで扱うには型定義ファイル(.d.tsファイル)が必要になるのですが、型定義ファイルを作るのはなかなか大変な作業です。

有名なライブラリなどはすでに型定義ファイルが作られているケースが多いので、一度 DefinitelyTyped を見てみましょう。

Github上からソースを落としてくるのも一つの方法ですが、npmやbower風にCLIでサクッとインストールツールtsdになります。

tsdはnpmでインストールすることができます。

$ npm install -g tsd # コマンド使えるようにするためグローバルに入れる
...

$ tsd --version # バージョン確認

>> tsd 0.5.7

tsd 0.5.7

tsdにもnpmでいうところのpackage.jsonや、bowerでいうbower.jsonと似た、プロジェクトにどんな型定義ファイルが必要かをまとめたtsd.jsonというものがあります。

新規に作るときはtsd initで作成します。

$ tsd init

>> tsd 0.5.7

-> written /Users/sskyu/dev/typescript/helloWorld/tsd.json

tsdの使い方はtsdまたはtsd -hで見れます。

型定義ファイルの検索はsearchを使うと思いきや、queryを使います。

Backbone.jsの型定義を探す場合はこれ。

$ tsd query backbone

>> tsd 0.5.7

 - backbone/backbone.d.ts : <head> : 2014-05-26 12:36

tsd queryは型定義ファイル名と完全一致で検索しているぽい。

前方一致とかで検索するときは文字列と*'または"で囲って使えばいいみたい。

$ tsd query 'backbone*'  # 他にBackbone関連の型定義ファイルがないか探す

>> tsd 0.5.7

 - backbone-relational/backbone-relational.d.ts : <head> : 2014-05-26 12:36

 - backbone/backbone.d.ts : <head> : 2014-05-26 12:36

# 2件しかヒットしないようです

Backbone.jsの型定義ファイルをインストールするときはこれ。

$ tsd query backbone --action install --save

>> tsd 0.5.7

 - backbone/backbone.d.ts : <head> : 2014-05-26 12:36

>> running install..

>> written 1 file:

    - backbone/backbone.d.ts

これで./typings/backbone/backbone.d.tsに型定義ファイルがインストールされました。

変数宣言のタイミング

JavaScript: The Good Partsを読んだことがある人なら、変数の巻き上げのこと知っているのでスコープの先頭でまとめて変数宣言しているかと思います。

たとえばこんなの。

var a = 1,
    b = 2,
    sum;

a = a * a;  // 途中何か処理を挟んで
b = b * b;

sum = a + b;  // 最後に合計を求める
console.log(sum);

最後から2行目でvar sum = a + b;としてもいいのですが、変数の巻き上げがあるので最初で定義しといた方が可読性があがります。

JavaScriptならこれでいいのですが、TypeScriptでは必要になった時に変数宣言するのがいいようです。

理由は変数宣言時の型推論にあります。
var a = 1, b = 2では右辺が数値型なので暗黙的にa, bそれぞれが数値型と解釈されます。
しかし、sumは変数宣言時に何も代入していないのでany型と推論されてしまいます。

any型を許容すると、数値型を意図しているのに文字列を代入できたりして、バグを産んでしまうので極力避けたいところ。 (コンパイルオプションに--noImplicitAnyを加えると暗黙的にany型を使っている部分でエラーを発生させられます)

なので、TypeScriptでは変数が実際に必要になった時に宣言するようにすると型推論を利用していい感じにコーディングできるそうです。

または、変数宣言時に型注釈を一緒に書くかなのですが、

var a: number,
    b: number,
    sum: number;

ここらへんのコーディングスタイルは好みの問題な気もしますね。

おわりに

1回読んだだけだとまだふわっとした理解なので、TypeScript触りながら慣れていきたいです。

TypeScript使ってて一番嬉しいのはインターフェースな気がします。
関数の引数にパラメータを集積したオブジェクトを渡すことが多いですが、決まった形式で渡せているのかチェックするのが面倒で、あれを型として定義しておきたいと前々から思ってまして。
そういうときにインターフェース使えば良さそう。

関数宣言の簡略系のアローがどうも見慣れない。
(頭のなかでこれが引数で、これが戻り値でと考えてしまう)
Coffee使ってたらすぐ馴染むのだろうけど。
thisが思った通り動くのが =>らしいので慣れておきたい。

まだまだメモ書きたくさんあるけど、時間の都合上感想はここまで。

最後に、TypeScript本(通称わかめ本)は読んで良かったと久しぶりに思えた本でした。
リファレンスという名の通り、TypeScriptを書くときは常に手元に置いておきたい本です。