typescript触ってみた ついでにunderscoreのinstance定義ファイルを作ってみた

主に自分が一番使っているcoffee-scriptとの比較

underscoreのは練習がてら作ってGithubにおいた
mizchi/underscore.d.ts https://github.com/mizchi/underscore.d.ts

書き味

構文の硬さがJavaが10 Python6 Rubyが3という記事をどっかで見たけど、同じように当てはめると、JS8 typescript6 coffee2という感じ。
coffee-scriptの超ゆるふわスタイルに慣れてると結構辛い感じはあるが、自分多分Coffeeについてある程度極まってる感じなので、あんまり比較しないほうがよさそう。
高階関数(後述)が簡単に定義できるのでJS特有のパラダイムには素直に応えられる。

""" multiline text """ がない
デフォルト引数がない

最初にunderscoreの型定義ファイルを書いた理由

JSのスーパーセットなだけに、イテレーションが貧弱

Lambda

結局自分はfunctionと書きたくなくてcoffeescriptを使ってるフシがあるのだけど、どのぐらい省略できるか調べてみた。

自分自身を返す f(x) = x はこう書ける

(i) => {return i}

ブロックだと複数行書けるが、returnが必須

もしくはブロック省略して

i => i

こちらはreturnが要らない

CoffeeScriptと違って 引数なしの()は省略できない

[1,2,3].forEach((i) => {
  console.log(i);
})

こんなふうに某関数型言語っぽく書くことも

var fuga: (number) => (string) => number
  = (a) => (b) => a * b.length;
console.log(fuga(3)("dafa"))

アノテーション

クラス志向というよりかはインターフェース志向?Golangっぽさも若干感じる。とりあえずJSの邪魔をしないanyが便利。

JavaScriptのスーパーセット

CoffeeScriptの辛かった点である、「jsコピペしてすぐ動かない」問題が解決した。
とりあえずコピペしてから徐々に置き換えるという段階を踏める。

末尾セミコロン

JSと同じような扱い。classフィールドでは;なしだと構文解析されない。基本末尾セミコロン嫌いなので可能な限り省略して書いてみたが、結局必要そう

エディタ

宗教上の理由(一方が好きというかは一方が嫌い)でVSが使えないのだが、SublimeTextで書いていたが補完はなかった。
まあ簡単そうなのでそのうち誰かが作るだろう。

instance

公式リポジトリのサンプルに型ファイル情報が少しついてる

  • express.d.ts
  • jquery.d.ts
  • jqueryui.d.ts
  • node.d.ts

todomvcにはBackboneモジュールに対して型アノテーションを追加していて参考になる。

declare module Backbone {
    export class Model {
        constructor (attr? , opts? );
        get(name: string): any;
        set(name: string, val: any): void;
        set(obj: any): void;
        save(attr? , opts? ): void;
        destroy(): void;
        bind(ev: string, f: Function, ctx?: any): void;
        toJSON(): any;
    }
    export class Collection {
        constructor (models? , opts? );
        bind(ev: string, f: Function, ctx?: any): void;
        collection: Model;
        length: number;
        create(attrs, opts? ): Collection;
        each(f: (elem: any) => void ): void;
        fetch(opts?: any): void;
        last(): any;
        last(n: number): any[];
        filter(f: (elem: any) => any): Collection;
        without(...values: any[]): Collection;
    }
    export class View {
        constructor (options? );
        $(selector: string): any;
        el: HTMLElement;
        $el: any;
        model: Model;
        remove(): void;
        delegateEvents: any;
        make(tagName: string, attrs? , opts? ): View;
        setElement(element: HTMLElement, delegate?: bool): void;
        tagName: string;
        events: any;

        static extend: any;
    }
}

curry化/ っぽくしたかったけど上手くいかなかった

var fuga: (number) => (string) => number
  = (a) => (b) => a * b.length;

// it works
console.log(fuga(3)("dafa"))

// it doesnt work
Function.prototype.proc = function() {
  var args, target, v;
  var __slice = [].slice;
  args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  target = this;
  while (v = args.shift()) {
    target = target(v);
  }return target;
};

console.log(fuga.proc(3, "dafa"))

Function型にprocがない。prototypeを拡張したことを認識されていない。
誰か教えてください。
公式サイトのリアルタイムインタプリタなら通ったので、コンパイルオプションでどうにかなるかも