##予防線
どの実装が ES6 Modules の実装としてまともなのかわからんのでなんとも言えんが、とりあえず TypeScript 1.8 にある ES6 Modules のようなものの実装では以下の技が使える。ES6 Modules の一般的なテクかもしれないけど、仕様を読む手間をケチったのでタイトルは具体化した。
TL;DR
import Foo from './foo';
import Bar from './bar';
export {
Foo,
Bar,
};
import * from SomeNamespace from './some_namespace';
SomeNamespace.Foo;
SomeNamespace.Bar;
// 更に export したい場合はこう
// (package の main とかでこうすると便利)
export {
SomeNamespace,
};
モチベーション
validators
├── base_validator.ts
└── hoge_validator.ts
foo.ts
こういうディレクトリ構造のとき、 foo.ts
で
const validator = new Validators.HogeValidator();
みたいに書きたいじゃん、というのが今日のお題です。
そもそも index.ts
(index.js
) っていいパターンなんですかね。もうここ5年くらい使ってるパターンなのでこれ以外の方法を知らないんですけれども。
1. Namespace (旧 Internal Module) 案 (ボツ)
/// <reference path="./validators/base_validator.ts" />
namespace Validators {
class HogeValidator extends BaseValidator { }
}
※base_validator.ts
とか index.ts
とかは自明なので脳内で補完してください。
一見いい感じに見えるが、 hoge_validator.ts
とかで import
を使った瞬間に namespace が動かなくなるのでダメ。(External) Module と Namespace は排他っぽい。これだと Node.js の標準モジュールすら満足に使えず、つらい気持ちとなる。
namespace を export すりゃいいじゃん、とも思ったが、import した namespace はマージできないのでファイル分割が死ぬ。ダメ。
2. 全部入りの Object を export default 案 (ボツ)
import BaseValidator from './base_validator';
export default class HogeValidator extends BaseValidator { }
import BaseValidator from './base_validator';
import HogeValidator from './hoge_validator';
export default {
BaseValidator,
HogeValidator,
};
import Validators from './validators'
const validator = new Validators.HogeValidator();
やったぜ!! でも、本当?
const validators: Validators.BaseValidator[] = [];
tsc says:
Cannot find namespace 'Validators'
fsck!!!!!!!
Object は Namespace ではない、とのことです。はい。
3. export { ... } を使う案 (せいかい)
See: TL;DR
まとめ
本当に ES6 Modules は反省して欲しい。