TypeScript1.0が出たのでジェネリクス試してみた

TypeScriptの知識は最初に出た0.8系で止まっているので、噂に聞いてたジェネリクスを試してみる。(ジェネリクス自体は0.9系からある)

型の表現力を試すときは、自分はいつもmap関数の型表現を定義してみることにしている。

function map<A,B>(list: A[], func: (a:A) => B): B[] {
    return list.map(func);
}
 
var strList: String[] = map<Number, String>([1,2,3], x => x.toString())
var strList2 = map([1,2,3], x => x.toString()) //型を省略しても引数から推論してくれる

このmap関数の表現ができる言語とできない言語がある。たとえばC++はだいぶめんどくさいことしないとできなかった。

    template<class T, class F>
    auto map(const std::vector<T> & vec, F fun) -> std::vector<decltype(fun(vec[0]))> {
        std::vector<decltype(fun(vec[0]))> ret;
        std::transform (vec.begin(), vec.end(), std::back_inserter(ret), fun);
        return ret;
    }

(これは1年ぐらい前に@krustfに教えてもらったやつ。C++14だともっと簡単になるかもしれない。)

Goはテンプレートを持たないので無名のインターフェースとかでごまかしつつやることになる。そもそも速度重視で型表現が豊富な言語じゃねーよ、ってのはググってるとたくさん見つかったので、そういうことなんだと思う。

とにかく、TypeScriptの標準のlib.d.tsじゃどうなってるんだろう、と Array をみると、map 関数は次のように定義されていた。

map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[]; 

だいたい予想通り。細かい挙動は @yaakaito の人のブログとか @vvakame さんのqiitaとか読めばわかる。

async, awaitはv1.1に

昔見た時はv1.0にはC#のasync相当のものを入れると聞いてたんだけど、さっきロードマップを見ると 1.1になってた。 そもそも ES6ジェネレーターを待つか、自前で定義するか難しいところなので、悩みどころなんだと思う。jsxはyield互換のコードを自力で生成してて辛そうだった。

TypeScriptのプロジェクト上の辛いところは、一応MSのプロダクトなので建前上IEで動かない機能つけるのどうなんだろうな、って展開になりがちな気がする。他にasm.jsとか…。