TypeScript の小ネタです。
react-native にはPlatform-specific extensionsという仕組みがあります。
これはファイルを拡張子を使って各プラットフォーム(Android/iOS)向けにモジュール参照先を切り替える仕組みです。
例えば次のように各プラットフォームごとにカスタマイズされたモジュールを作成したとします。
BigButton.android.ts;
BigButton.ios.ts;
これを利用するときは次のように呼び出すことができます。
import BigButton from "./BigButton";
ところが、これを TypeScript でやろうとした場合、モジュール参照先にファイルが存在しないためエラーとなります。
// TS2307: Cannot find module './BigButton'.
import BigButton from "./BigButton";
今日はこれを解消する方法の紹介です。
.d.ts を作成して回避する
回避方法としては、次のようなBigButton
の型定義ファイルを作成するだけです。
// BigButton.d.ts
import * as ios from "./BigButton.ios";
import * as android from "./BigButton.ios";
declare var _test: typeof ios;
declare var _test: typeof android;
// ここでモジュールの型情報を提供する
export * from "./BigButton.ios";
これでコンパイルエラーは消えました。
この仕組みで興味深いことは、_test
の Type を再割り当てすることで、各プラットフォームのコードの差異を検知することができることです。
試しにモジュールの中身を違うものに変えてみたところ、次のように差異があることを検知することができました。
TS2403: Subsequent variable declarations must have the same type. Variable '_test' must be of type 'typeof import("BigButton.ios")', but here has type 'typeof import("BigButton.android")'.
まとめ
TypeScript のコンパイラの方でサポートして欲しいという要望があったようですがクローズされてしまったようです。 当分の間は上で紹介した方法で回避するしかなさそうです。
今回のトリックも上の Issue からいただきました。最初に思いついた人すごいですね。