名前構造: 補足

TypeScript の型定義ファイルと仲良くなろう - Hatena Developer Blog は良い解説だが、entity, container がイマイチ不明瞭。

まず、entity とは、型付きの名前(値はない)、または名前と値のペアのどちらか。名前があることを強調したいなら named entity だ。container は entity のリストであり、同名のエンティティが複数在るかも知れない。出現の順番は意味がある。

課題は:

  1. 特定のエンティティに対して、その親コンテナとは何か?
  2. 特定のエンティティに対して、そのルートコンテナとは何か?

まず、エンティティの入る“場所”は、名前構造の名前コンテナのパーティション。「パーティション=コンテナ」という用語コンフリクトが起きている。

親コンテナは、エンティティが所属するパーティションを直接含むコンテナ、でいいだろう。

ルートコンテナだが、これは、あるコンテナが「ルートだ」という話ではない。エンティティに対して、そのルートコンテナという概念がある。

  1. エンティティがプライベートな(エクスポートされてない)なときは、親コンテナがルートコンテナ。
  2. エンティティがパブリックな(エクスポートされている)ときは、親コンテナのルートコンテナがそのエンティティのルートコンテナ。

以上の定義には、コンテナ自体もエンティティであることが含意される。したがって、コンテナの親コンテナという概念もある。

大域名前空間〈global namespace〉とは、名前コンテナであり、絶対的なルート(相対的なルートや、エンティティのルートコンテナではない)。したがって、大域名前空間=大域コンテナには親コンテナがない。

次の概念が紛らわしい。

  1. 大域コンテナ=絶対的なルートコンテナ
  2. エンティティのルートコンテナ
  3. 相対的なルートコンテナ 例:モジュールのルートコンテナ

TypeScriptの場合、namespace は自動的にパブリックになるようだ。したがって、namespaceが記述されたモジュールスコープから飛び出して大域コンテナ内に名前空間名が配置される。

同様に、interfaceも自動的にパブリックになりパブリックなinterfaceならそのスコープはファイルモジュールから飛び出す。さらにオープンエンドであることから、他のファイルでインターフェイスの内容を足すことが出来る。

interfaceがオープンエンドでクローズドじゃないのは奇妙な感じがするが、柔軟性を確保するためにしょうがないのだろう。モンキーパッチじゃなくて、コンパイル時の動的パッチのようなものが出来る。モルモットパッチくらい?

[追記]TypeScriptの場合、.tsファイルがモジュールかスクリプトかはimport/export宣言のあるなしで区別して、スクリプトの場合は、大域コンテナ〈大域名前空間〉に直接貼り付ける感じになる。モジュールだと、モジュールのスコープを作ってシールドする。シールドがあるかないかがモジュールとスクリプトの差異。[/追記]