namespace / module
| 対応: | TypeScript 1.0(2014) |
|---|
名前空間は主に既存のコードの保守やライブラリの型拡張で使用します。新規プロジェクトではESモジュール(import/export)を使用してください。
『namespace』は TypeScript 独自のモジュール管理機構です。関連する型・変数・関数をひとつの名前空間にまとめることで名前の衝突を防ぎます。また『declare module』を使うと、既存のモジュールの型定義を拡張できます。
構文
namespace NamespaceName {
export interface SomeInterface { /* ... */ }
export function someFunction(): void { /* ... */ }
}
// 宣言マージ(同名の namespace を複数定義すると自動的にマージされる)
namespace NamespaceName {
export const newValue = 42;
}
// グローバルの型を拡張(declare module で既存モジュールを拡張)
declare module 'express' {
interface Request {
user?: { id: number; name: string };
}
}
サンプルコード
// namespace の基本
namespace Geometry {
export interface Point {
x: number;
y: number;
}
export function distance(a: Point, b: Point): number {
return Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2);
}
}
const p1: Geometry.Point = { x: 0, y: 0 };
const p2: Geometry.Point = { x: 3, y: 4 };
console.log(Geometry.distance(p1, p2)); // 5
// 宣言マージの例
namespace Geometry {
export interface Point {
label?: string; // 既存の Point インターフェースに追加
}
}
// declare module でグローバル型を拡張
// global.d.ts
export {}; // このファイルをモジュールとして扱うために必要
declare global {
interface Array<T> {
first(): T | undefined;
}
}
// 実装側
Array.prototype.first = function () {
return this[0];
};
実行すると次のように出力されます。
npx ts-node ts_namespace.ts 5
概要
現代の TypeScript 開発では、モジュール分割に ES モジュール(『import』/『export』)を使うのが主流です。『namespace』は ES モジュールが普及する以前の時代に使われていた仕組みで、新規プロジェクトでは基本的に使いません。
ただし、宣言マージ(declaration merging)の文脈では今でも活用されます。同名の namespace・interface・モジュールを複数の場所で宣言すると、TypeScript が自動的にそれらをひとつにまとめます。特に 宣言ファイル(.d.ts) でライブラリの型を拡張する場合(『declare module』でモジュールを拡張するパターン)は現役で使われています。
Express の Request 型に『user』プロパティを追加する例のように、外部ライブラリの型を安全に拡張するために『declare module』は特に有用です。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。