以前こんな記事を書きましたが、Haxe 3.2で状況が改善したようです。
とりわけ嬉しいと思われるのは
@:nativeマクロがクラスフィールドをサポート
可変長引数のサポート
Union Types的な機能をサポート
でしょうか。
nativeマクロがメンバ変数やメソッドにも使えるようになった
@:native
というマクロは、以前は型名のエイリアスにしか使えませんでした。そのため、利用法としてはモジュール名が大文字から始まる(Haxeではモジュール名は小文字からはじまらないといけない)というようなケースくらいにしか使えませんでした。
ところがJavaScriptでは、$
記号や、catch
などの予約語をメソッドに使うなどの行為は実際チャメシ・インシデントです。
一応Haxeでも、propertyを使ってクロージャを返すような型定義をする(うろ覚え)……などの裏技で回避出来るんですが、@:overload
が必要になった時点で詰みます。
かといって全てを委譲するようなコードを書くのはただでさえ不毛で面倒なexternの作成作業が倍点でめんどくさくなる上にオーバーヘッドがかかるという悲しい現実。
これでbluebirdみたいなPromise/A+のAPIを実装したexternが使える!
特に予約語が使えないのは致命的です。
この制限のせいでPromise/A+のような超重要APIのexternが利用できませんでした。なんとかしようとしたんですが、途中でめんどくさくなって投げた覚えがあります。
重要度は低いですが、RxJSも予約語を使いまくるので難儀した覚えがあります。
どういう変換が行われるか
ちょうどいい感じにRxJSのexternを作りかけていたリポジトリがあったので、試してみました。
hachibeeDI/RxJS-haxe · GitHub
まず、以下のようなメソッドを定義します。ついてに@:overload
と協調して動くことも確認してみます。
@:native("catch") @:overload(function <T>(sources: Array<Observable<T>>): Observable<T> {}) public static function catch_<T>(sources: Array<IPromise<T>>): Observable<T>;
これを
// Haxe ob.catch_(function(x) {return null;});
のように呼び出すと
ob1["catch"](function(x) {return null;});
という風に変換されます。
ヤッター!
ドットによるメンバの呼び出しではなく、hashスタイルの属性呼び出しに変換されているあたりが気になりますが、ともあれこれで正常に動いてくれるはずですね。
Haxeにおける可変長引数とUnion Types
それぞれhaxe.extern.Rest<T>
とhaxe.extern.EitherType<T, U>
で使えます。
使い方については、まぁなんとなくわかると思います。
詳しくは公式のexternについてのマニュアル Externs - Haxe - The Cross-platform Toolkit を参照しましょう。
特にUnion Typesのサポートは色々と嬉しいですね。色々と問題の多いoverloadを使わなくても良くなります。
とりあえずこれらの機能でTypeScriptとおおむね同等なJS用の型表現が出来るようになったのではないでしょうか。
まとめ
結局のところ、色々あったつらいところの一つが解消されたっていうだけなんだけども、その中でもかなりしんどい度が高いものだったのでこれは嬉しい。もっとextern増えてくれ。
あるいは「予約語や記号はサフィックスに_
をつける」みたいなルールをつけて、.d.ts
から変換をかけるようにすれば良いわけで。
もう書く機会ないかも……って思ってましたけど、これは復活ありえますね。Angularみたいに魔術的なライブラリを再現するのは難しいですけど、React( + 薄いFlux)くらいならHaxeでも全然なんとかなります(多分)。
その上、コードを解析してより深いコンパイル時最適化をかける実験的オプションが追加されたり、enum Abstruct
が可能になったり……などなど、エキサイティングな機能がモリモリです。
ついでにですけども、コンパイラに付随しているコード補完や解析系の機能も強化されてます。vaxeにパッチ送らないと(使命感)
まだ全部の機能を追えていないので、チェックしていきたいですね!
おしまい!