Skip to content

Instantly share code, notes, and snippets.

@teppeis
Last active April 11, 2016 08:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save teppeis/d7f40170902a9a4144a2 to your computer and use it in GitHub Desktop.
Save teppeis/d7f40170902a9a4144a2 to your computer and use it in GitHub Desktop.
TypeScript用フルスタック型付きライブラリのご提案 (https://gist.github.com/teppeis/10659631 は間違えて消しちゃったので再投稿)

TypeScript用フルスタック型付きライブラリのご提案 #葉桜JS

https://github.com/teppeis/closure-ts

We need KATA!

異論は認めない。

There are many Typed-AltJS.

  • M社
  • G社
  • D社
  • H

Typed-AltJS requires a typed library.

静的型付け指向ではないライブラリに型定義を与えて使っても型の力は活かせない(古くてごめん)

Closure Library!

現存する唯一のフルスタック静的型付けJSライブラリ(当社調べ)

closure-ts: Use Closure Library in TypeScript

  • Closure LibraryのJSDocとコードをDoctrineEsprimaでパースしてTypeScript用の型定義ファイル(d.ts)を吐き出す。
  • まだ昨日数時間実装しただけのPoCレベル
  • いくつかのファイルは生成に成功

特徴

  • TypeScript, Closure Toolsの既存資産はそのまま活用できる(Powered by IDEs, Grunt, Closure Compiler)
  • さまざまなTypeScriptの使い方に対応
    • Internal modules
    • External modules (AMD/CommonJS)

汎用型定義生成の夢

  • 1つのライブラリを全言語で動かす
    • Closure Compiler
    • TypeScript
    • Haxe
    • JSX
    • Dart?
  • Write once, run anyware
  • ATD (Abstract Type Definition) ?
  • doctrineが既に近いことをやっている
// JSDocの型定義
/**
 *@type {Array<string>}
 */

// Doctrineのパース結果
{
    "description": "",
    "tags": [
        {
            "title": "type",
            "description": null,
            "type": {
                "type": "TypeApplication",
                "expression": {
                    "type": "NameExpression",
                    "name": "Array"
                },
                "applications": [
                    {
                        "type": "NameExpression",
                        "name": "string"
                    }
                ]
            }
        }
    ]
}
  • JSコードをEsprimaがASTで抽象化したように、JSDocの型情報をdocrtineが抽象化する。
  • EstraverseのDoctrine版、doctraverse みたいなものが簡単に書ける。

言語による仕様差異

  • ただし、Doctrineが抽象化できているのは型情報のみ。
  • 型情報の外側に言語依存で仕様が異なるものがたくさんある
    • Module
    • Interface
    • Function
    • Class
    • Variable
    • Generics
    • Enum
    • UnionType
    • Null
    • Undefined
    • Rest parameters
    • ...
  • 各言語向けの型定義生成では、結局このレイヤーの泥臭い変換が必要。。
    • 例えば以下のコードに対して、doctineは「string型の引数strを1つ取る関数がある」という情報しか扱わない。mynamespace.foo.barがmoduleとvarなのか、オブジェクトとメソッドなのか、intefaceとstaticメソッドなのか、解釈は個別の実装ごとに必要。
/**
 * @param {string} str
 */
mynamespace.foo.bar = function(str) {};

TypeScriptへの変換ではまるポイント

  • すべてnullable(プリミティブも)、non-nullableがない
  • UnionTypeがない @type {number|string}
    • オーバーロードを強要される
  • d.ts の書き方に流儀がいろいろあって難しい
    • 参考: TypeScript Handbook: Writing .d.ts files
    • module, interface, declare, exportとかいろいろある
      • module var vs. anonymously-typed var vs. interfaced-typed var
      • standard class vs. decomposed class

俺達の型付けはまだ始まったばかりだ!

第一部完。次回作にご期待ください。

@teppeis
Copy link
Author

teppeis commented May 11, 2014

https://gist.github.com/teppeis/10659631 を消しちゃったのでコピーをpublicにしておく。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment