JSXでjQueryを動かす上での障害
飽きてきたのでやる気が0になる前に気づいた点を公開しておく
- $は識別子に使えない。
- jQuery.isはisがJSXの予約語なので使えない。is_とかにリネームする?
- jQueryがjQuery(...)もjQuery.fooもできる存在なのが厄介。僕も今の実装ではclass jQueryを作ってコンストラクタのnew jQuery(...)とstatic methodのjQuery.fooを使う形になっているけども、見た目をjQueryに似せるのをやめてjQuery(...)的な使い方は全部きちんと名前付きで呼べ(jQuery.find(...), jQuery.ready(...), etc)という方がよい気がする。
- jQuery.findの返り値は[0]とかができる「Arrayのような何か」だが、これは実はArrayではないのでJSXではArrayへのキャストが出来ない。
- jQuery("p") as Array.
がnullになって悩んだ。 - Map.
にキャストして["0"]でアクセスする必要がある。
- jQuery("p") as Array.
- JSXには「型T1または型T2の値が入る型」(OCamlでいうところのvariant型)を定義する方法がない。
- 例えばjQuery.textは{(string|!jQuery)}を返してくる。JSXでは「variantで受けておいてプログラマがjQueryだと思うならas jQueryでキャストして使え」となって、キャストが挟まるのでメソッドチェーンで書くことができない。
- もしくはjQueryラッパーの中に「stringまたはjQuery型」を表現するためのクラスを用意しておいて、それの.as_string()と.as_jQuery()がキャストを隠蔽するって方法ならメソッドチェーンはできるだろうな。
- 例えばjQuery.textの引数の型は{(string|function(number,string))=}。これはJSXでは表現できないのでvariantにするしかない。結果的にjQuery.textはvariantを取ってvariantを返す関数になる。うーん、型チェックはどこへ…。
- 例えばjQuery.textは引数が0個の場合と1個の場合がある。JSXには変数の省略がないのでこれを2個のメソッドのオーバーロードで表現しないといけない。
一言でまとめると「jQueryが酷い」なんだけども、JSXの側をどういじったら一番楽にjQueryを使えるか考えた結果「複文の粒度でsuppress checkType できるようにする」じゃないかと思った。Closure Compilerは関数の粒度でのsuppress checkTypeができて、それをやれば関数内での型エラーが全部握りつぶされる。これは粒度がでかすぎて不便なので言語をいじれるメリットを生かしてもっと小さい粒度でのsuppressを導入すればいいと思う。
suppress("checkType"){ jQuery(...).foo().bar().baz(); ...; }
追記、haXeのことは全く知らなかったんだけども、今朝僕が必要だと考えた上の構文はhaXeには既に実装されているそうだ!
untyped { ... }
自分が「こうあるべきだ」と考えた設計が別の所で採用されているのを発見するのはうれしいことだなぁ。haXeのファンになりそうだ。
追記、なんかたくさん書いてしまったけど、一言でまとめるなら「JSXでjQueryを使うのはしんどい」かな。