Namespace(名前空間)とは、論理的に関連するエンティティをまとめるために、ES6以前の時代から存在するコードの組織化メカニズムです。これは、大規模なプロジェクトを構築する際に、クラス、関数、インターフェース、型を1つの名前空間内でグループ化し、名前の衝突を避け、コードをより読みやすくするのに役立ちます。
問題提起:JavaScript ES6標準の登場以前、開発者はIIFE、オブジェクト、名前空間を使用してモジュール性を模倣していました。TypeScriptは、コードをグループ化するために、namespace(以前のinternal module)というキーワードを導入しました。
問題点:現代のモジュール(ES6 Module)が標準となり、両方のアプローチ(namespaceとモジュール)が並行して存在するため、アーキテクチャ設計で混乱が生じています — いつnamespaceを使用し、いつmoduleを使用するのが良いのでしょうか?
解決策:Namespaceは、ヘルパー関数や型を完全にTypeScriptプロジェクト内でグループ化するのに依然として役立ちます(例えば、outFileによる単一JSファイルの生成時など)。ファイル間でコードを分ける場合、特にnpmや現代のビルドツールを使用する場合は、モジュールを使用する方が適切です。Namespaceは内部ライブラリ、型の宣言、および1つのファイル内での構造化や古いコードに必要な場合に多く用いられます。
コード例:
namespace MyMath { export function add(a: number, b: number) { return a + b; } } console.log(MyMath.add(2, 3)); // 5
主な特徴:
異なるファイルからnamespaceを統合すると、1つのnamespaceになりますか、それとも複数になりますか?
TypeScriptは_宣言のマージング_を行い — 名前が一致する場合、異なる名前空間の部分が正しく接続され、同じスコープ内にある場合は1つに統合されます。
// mathA.ts namespace MathUtil { export function sum(a: number, b: number) { return a + b; } } // mathB.ts namespace MathUtil { export function mul(a: number, b: number) { return a * b; } } // コンパイル後、MathUtilは両方のメソッドを含む
namespaceをモジュールのようにimport/requireで使用できますか?
いいえ、namespaceにはデフォルトエクスポートまたは名前付きエクスポートがないため、ES6の標準構文でインポートすることはできません。Namespaceは、JavaScriptのモジュールに変換されない純粋にTypeScriptの概念です。
他のファイルからimportを通じてnamespaceの値をインポートできますか?
いいえ、他のファイルからnamespaceにアクセスするには、参照の使用(/// <reference path="..." />)またはoutFileを伴ったコンパイルが必要であり、importを通じたインポートは不可能です。
古いプロジェクトでロジックを数十のnamespaceに分割し、同じ名前が複数のファイルに出現したため、予期しない統合や衝突が発生することがありました。モジュラーアーキテクチャに移行する際、コードの移行が非常に手間になりました。
長所:
短所:
大規模なライブラリでは、index.d.tsという1つのファイルでnamespaceの宣言を通じてAPIを定義し、すべての型とインターフェースをコード実装なしで一元化しました。これにより、ライブラリの消費者を迅速に型付けし、チーム間の契約を簡単に更新できました。
長所:
短所: