TypeScriptでChromeのExtension書いてハマったとこメモ
概要
ChromeExtensionをTypeScriptで書いてみてた。
TypeScript化しつつあるブツはこちら。
SublimeSocketでのTypeScriptコンパイル機構
ChromeExtensionsのJSをTypeScript化することのメリットは、今回の場合下記を目論みつつ。
・クラス!! クラス!! クラスがホシイ! デフォで!!
・extendsを使った振る舞いの置き換えが簡単に素敵!
・コンパイル時型チェックあるしミスに気付くチャンス増えてラク
などなど喧嘩売ってるように見えなくもない感じ。
成果物
各言語対応に簡単に対応したいため、extendsでmethod実装さえすれば動くようにした。
https://github.com/sassembla/SublimeSocket/tree/dev/tool/chromeClients/TypeScriptClient
ハマったとこ列挙してく
1.chrome.*とのお付き合い
TypeScriptさんはchromeなにやらのことを知らないので、
declareで何が来ても吃驚せずコンパイルしてもらう事にします。
declare var chrome;
で、
chrome.browserAction.onClicked.addListener(function(tab) {};
chrome.windows.getAll (function(windows) {});
chrome.browserAction.setIcon({path:"images/icon-inactive.png"});
とかがTS内で使えるようになるので、他の、かっちり構造的にすべきところに注力する事が出来る。
他にはWIndow系とかがあるけどこの辺はもう普通のTSの使い方と変わらんす。
d.tsを探せばどっかあるだろとか思ったんですが、なかなか変化しそう+使用するメソッドも関数渡しがメインだったので、今回は使ってないです。
ちなみにd.tsをつくった方、こちら。
borisyankov / DefinitelyTyped
https://github.com/borisyankov/DefinitelyTyped
の、
https://github.com/borisyankov/DefinitelyTyped/pull/93/files
あたり。
このひとすげーな。
2.extendsとロード順
ChromeのExtension、使用するjsをmanifest.jsonに定義するところについて。
~中略
"background": {
"scripts": [
"Something.js"
]
},
~中略~
とか書くわけだけど、
TypeScriptで、
クラスParentとクラスChild(ChildはParentをextendsする、みたいなとき、
class Child extends Parent {
}
class Parent {
}
scriptsのロード順(!)を気にする必要がある。
manifest.jsonファイル内のscripts配列の要素のアタマから順に読んでるんだと思うので、
"background": {
"scripts": [
"Parent.js", "Child.js"
]
},
で、実際のクライアント上でもちゃんと動く。
読み込む順にv8に喰わせてるかなんかだと思うので、
順番をChild.js -> Parent.js とかにすると、Parentなんか知らねーよ、とエラーで怒られる。
もちろんTS自体のコンパイル正否とは無関係に。
複雑になってくると詰む。面倒くさくて。
→extends関係を考慮して云々するより、concatnateしてしまえばいいじゃない!
と思ったんだけど、これはこれで下記3のカドに小指がぶつかる。
3.--outオプションによる死亡
コンパイル物を1ファイルに纏めるべく、tscに--outオプションを付けるなどすると、
Extension読み込み時に
Uncaught TypeError: Cannot read property 'prototype' of undefined
が、出る。
原因箇所はこんな感じ。
条件としては、
・extendsを使用している
・--outで固める
の組み合わせ。
一発で読んじゃえばいいじゃない→中身の順番でアバー というパターンにハマった。
extends自体の定義で問題が起きてる。
ちゃんと読むとかすれば解決できると思うけど、
manifest.json のscrptsの記述順番による解決の方がなんぼかラクだったので、日和って回避した。
ChromeExtensionsでのコードが大規模になった時(って来るの? 来ないでしょ)不味い。
例では、class WS が class WSControlBasement をextendsしてるので、そのための定義順だと思うが、
extendsされるクラスが先に定義されてないから駄目なんじゃないかなあと思うなど。
あっ名前については見逃してください、、あくまで仮です。
他に、staticとかもヤバい予感がする。
順番指定して--out、とかもイヤな話だしなあ、、
オプションについては下記が自分の覚えてるすべてなので、
http://sassembla.github.io/Public/2012:10:20%2022-46-41/2012:10:20%2022-46-41.html
現行のオプションを試すともっといろいろ面白い事が出来るかもしれない。
コレ書いてる時の最新、0.8.3では、tsc.jsの24502行目から先につらつら書いてある。
無くなってるオプションもけっこうあるような。
4.chrome.*で発生したエラーのデバッガでの表示位置が微妙にずれる
chrome.*系のメソッドは、TSからはdeclareしてるだけだと、特にそれらのメソッドについての型チェックが行われるわけではない。
chrome.*をd.tsで定義してればまともに出る、、かなあ、、 sourcemapの出番だよなー。
いちおうどうズレるかの例として、
chome.browderAction.onClicked に渡すパラメータを間違えると、下記エラーが出て、エラー行の表示が可能なのだが、
正し、エラー行の表示は原因行から若干”上”の行になる。
下の画像では、console.logで出た事になってる。
このTips、ぶっちゃけts関係ない。
以上!