飴屋

フロントエンド/TypeScript

TypeScriptを導入しようと思ったので、そのためにやったことを書きます。TypeScriptの一番の特徴は変数や引数や返り値に静的に型情報をくっつけることです。これがどの程度動作パフォーマンスに影響するのかまだ計測していませんが、そこにあんまり期待していません。(WebAssemblyと関係してくるとまた違うのかな。)型情報を付けると、変数の扱いが厳密な分、デバッグが楽というか、それ以前にリントやコード補完をエディタが頑張ってくれるようになるのがよさそうに思って始めました。

JavaScripptで書いていた疑似classをclassに書き直す

JavaScriptではprototypeを使って、なんちゃってclassを作っていた時代がありました。いくらか問題はありましたが、目的は果たしてくれるので、使い続けてきましたが、TypeScriptを導入するのでちゃんとclassとして体裁を整えることにしました。

function Hoge() {
this.fuga = 10;
}
Hoge.prototype = {
piyo: function(){
return 'hogeのfugaは' + this.fuga;
}
}

Hogeクラスがfugaプロパティとpiyoメソッドを持つ場合、↑こんな表現にしてました。

class Hoge {
fuga: number;
constructor(){
this.fuga = 10;
}
piyo(){
return 'hogeのfugaは' + this.fuga;
}
}

それをこんな風に書き換えることになりました。この例だと単純に書き方が変わっただけなので、簡単そうです。量が多いので、心を機械にして少しずつ進めることになります。一つだけ型情報numberがつきましたが、その辺にTypeScript感が表れています。あんまり頑張って型情報をつけようとすると疲れてしまうので、わかりやすところから手を付けて、無理せず型情報をつけない(any型になる)方針で進めます。

jQueryがガッツリ使われたJavaScriptをTypeScriptに移行したい

jQueryについては最近、採用しないケースも多いですが、古いシステムではなかなか食い込むように使われているので、いきなり除外するわけにはいきませんでした。ましてや、今回取り組んでいるのは、複数のバージョンのjQueryが同居する変わった構成だったので、nodejsで便利なパッケージが提供されていても扱い方がすぐにはピンときそうにありません。

declare var $;

わからないものには蓋をするようにアンビエント宣言を使って、リントが提示する問題点をなかったことにするのでした。おいおい解決していきましょう。今はやみくもに前に進むことにします。$はjQueryオブジェクトの短縮表現でよく知られていると思いますが、これの存在だけTypeScriptのコンパイラに伝えてあげました。

TypeScriptだから型情報を付けたい

基本的にstringとnumberはよく出てくる型なのでポチポチつけていきました。あとはbooleanとか。配列はいくつか定義の仕方があるようですが、中身が決まってるケースが多かったので、string[]、number[]で済んでいます。

よくobject({})を使って、辞書的な使い方をするのですが、名前をつけてデータを保存する場合「{[key:string]:any;}」としてます。

const obj:{[key:string]:any;} = {
a: 'aaa',
b: 123,
c: () => {void}
};

逆に自分が作ってない部分、主にJavaScriptにもともと備わっているクラス群には、TypeScriptによってしっかり型が定義されていた。親子のクラスはキャストしたい場面がチョコチョコ出てきたので「as」を使って、文法エラーを沈めました。

//let node:Node
if (node.nodeType == 1) console.log( (node as Element).tagName );

ついでにやっていったこと

  • 変数宣言のvarをconstかletに書き直していった。TypeScriptとは関係ないです。
  • 省略可能な引数に「?」をつけた。引数省略時に初期値をつけるやつは今のところないけど、出てきたらつけてみよう。

疑問に思ったこと

Type Assertion

型情報をキャストしなくてはならないことが頻発したので、どうするのがいいかなと思いつつ。とりあえず型名を明示してあげることにしています。Type Assertionと呼ぶらしい。

var a:hoge = <hoge>fuga;
var b:hoge = fuga as hoge;

二通り書き方があるけどなんか理由があるのでしょうか?