TypeScriptでType Providerを実現する構想

| No Comments | No TrackBacks

途方もない空白期間の後にしれっと書いているけど、ここはもともとメモ置き場だし、まとまった内容はだいたい他の場所に書いているので問題ない。ここに書いているのは、要するにまとまっていないアイディアである。

そんなわけで今日はTypeScriptをGNOME開発で使うにはどうするのがいいか、について考えてみる。

現在のGNOME開発のトレンドは、主にJavaScriptを使うということになっているようだけど、実態はC + 任意の言語 ということらしい。その心は、Cおよび好きな言語でアプリを書けるようにしておけ、ということだそうだ。Cをサポートするのは、GNOMEの基本的な方針ということなのだろう。

古いGNOMEのモデルだと、任意の言語、の部分は、それぞれの言語のバインディングが担うことになるわけだけど、2010年代のわれわれはそれが各言語バインディングごとに追いついたり追いつかなかったりで、理想的には機能しない、ということを知っている。

その問題を解決するために、GNOMEにはgobject-introspectionというAPI公開仕様が導入された。gobject-introspectionをサポートしている言語ランタイムでは、使いたいGNOMEのライブラリがgobject-introspectionに準拠していれば、特別にその言語バインディングを作成する必要はない。

さて、現在のGNOME 3.xでは、JavaScriptが標準としてプッシュされている。gnome-shellなどはJavaScriptで拡張を書くことが出来る。GNOMEのJavaScript実行環境には、spidermonkeyベースのgjsとwebkitベースのseedという実装が存在していて、どちらもgobject-introspectionに準拠している。これらのJSランタイム実装は、gobeject-introspectionを活用して、API情報をクエリして、JSオブジェクトに対するメソッド呼び出しを適宜解決して、そのgobjectに対するネイティブ呼び出しを実現する、というわけだ。これは少なくとも使い方としてはORBitだのBonoboだのと言っていた時代よりははるかに簡単だ。

さて、gjs(seedがBlinkで使えるかどうかは知らないが、Apple専用となったWebKitを使う気は全く無いので、以降gjsについてのみ扱う)でgobject-introspectionのgirを経由してAPIを「使える」ことは分かった。一方で、プログラムの開発時には、JavaScriptでは型情報が無いので、静的型付け言語を使うことで、コード補完などを実現できるようにしたい。

というわけで、TypeScriptを使いたい。TypeScriptは、JavaScriptにコーディング時の型情報を提供するものだ。TypeScriptはどうやって型情報を取得しているかというと、バージョン1.5の現在では、主に型情報を定義したTypeScript (d.ts)を参照して、型情報を構築している。AMD (asynchronous module definition)を利用することも可能だ。

(実行時には型情報は無いわけだが、gobject-introspectionのAPIで何とかなるのではないかとは思う。gjsが実現しているからといって、その仕組みが開発時に、すなわちTypeScriptで、そのまま使いまわせるわけではない。)

というわけで、現在の仕様に準拠するかたちで、GNOME開発でTypeScriptを使いたい場合は、このd.tsファイルをgirファイルから構築してしまえば良いわけだ。

しかし、これはあまり理想的ではない。これでは、girが変換されてd.tsが提供されたAPI以外については、「バインディングが提供されていないAPIはサポートされない」状況に近い。現実的な問題としては、DefinitelyTypedに誰かが登録したd.tsに対応するgirは、d.tsの利用者(プログラムの開発者)の手元にある各ライブラリと、バージョンが合わないかもしれない。出来ることなら、誰かがわざわざAPIを変換しなくても、girのリポジトリを、直接、型情報リポジトリとして使えるようにしたい。

これを実現するためには、typescriptコンパイラそのもの(tscおよびそのLanguageService)に手を入れなければならないだろう。しかし、typescriptそのものにプラットフォーム固有のgobject-introspectionのサポートを組み込むというのは、やはり抵抗感がある。tscはValaのようなGNOME-centric languageではない。

おそらく、ここで最も望ましいアプローチは、F#のType Providerのような仕組みなのではないか。TypeScriptの場合、実行時には型情報は存在しない。コンパイル時に型情報を解決出来れば良い。F#ではopenキーワードを拡張することで、Type Providerの仕組みを実現した。同様のことが、TypeScriptでも実現できるのではないか。

実のところ、JavaScriptライブラリにAPI情報を提供する仕組みは、他の実行環境等にも存在していて、「型情報をxxxから取得できるようにしろ」という要求にはissuesやpull requestsの前例がある。

  • JSDocからのAPI情報取得 https://github.com/Microsoft/TypeScript/pull/2646
  • node.jsのnode_modulesからの情報取得 https://github.com/Microsoft/TypeScript/issues/247

AMDサポートも、この(既に実現している)一種と言える。

また、QMetaObjectのようなものを(gobject-introspectionとsmokeを経由せずに)サポートしようと思ったら、やはり独自のtype providerがあれば実現できる。

これらのような例を考えるに、おそらくそれぞれを個別にサポートするよりは、何らかのかたちで標準化されたtype providerをサポートするようにした方が望ましいのではないか。

node_modulesサポートのissueは、TypeScript 2.0というカテゴリでまとめられているので、この辺りの議論は、もしかしたら早めに出したほうが良いのかもしれない。個人的にTypeScriptにもGNOME開発にも全力でコミットするつもりがないので、tscパッチなど何かしらの具体的な実装を伴わないアイディアで終わってしまっているのが残念なところではある。気が向いたら実装に着手するかもしれない。

No TrackBacks

TrackBack URL: http://veritas-vos-liberabit.com/noteon/mt-tb.cgi/172

Leave a comment