TypeScriptでブラウザ用のコードを書く場合にWebPackなどでソースをまとめているんだけど、最終的に出力するJavaScriptのコードをライブラリとアプリで別にしたいといった場合にどうしたらいいのか、という方法。
具体的には、RxJSをライブラリとして使い場合に普通にimport
を使って
import * as Rx from 'rxjs/Rx' |
などというコードをtsc
でコンパイルすると
; |
などとrxjs/Rx
をrequire
するコードが出力され、WebPackによってRxJS
と一体になったコードが出力される。
これをライブラリをグローバル変数Rx
に格納することにして、アプリ側からは参照だけでrequire
しないようにして、WebPackでまとめたアプリのコードにライブラリが結合されないようにしたい。
declare:anyを使う方法(型情報が失われる)
declare
を使って、グローバル変数Rx
をany
で宣言してやる方法がある:
declare const Rx: any |
一応これで実現できるのだが、コンパイル時に型情報が使われなくなってしまうので、せっかくのTypeScriptのメリットが薄れてしまう。
referenceを使う方法(デフォルトを参照できない?)
外部ファイルの型情報を取り込む方法に、reference
コメントを書く方法がある:
///<reference path="./node_modules/rxjs/Rx" /> |
reference
で型情報を取り込めるが、Rx
はデフォルトエクスポートでそれをreference
で参照する方法がわからなかった…。
自分で定義ファイルを書く方法(面倒)
自分で.d.ts
ファイルを作成して、reference
で参照する方法もある:
// rxdef.d.ts |
// main.js |
ただ、ライブラリの定義を自前で書くのは二度手間だし更新するのが大変になってしまう。
import文で型情報だけを使用する方法
TypeScriptで複数ファイル構成する2つの方法 - teppeis blogの「動的遅延ロード」の項目にrequire
した外部モジュールの型をtypeof
で使用する例が書いてあった。これを参考にしたところimport
でも同様のことができた:
import * as IRx from 'rxjs/Rx' // 念のため、名前をIRxと変更 |
外部モジュールをimport
(require
)しても、実体を参照しなければtsc
でコンパイルした結果にはrequire
されないことがわかったので、これで望みの動作が達成できる。
TypeScript…ちょっと難解です…。