TypeScript モジュールシステム
モジュールシステムは、現代の TypeScript 開発の基盤です。
TypeScript は ES Module 構文を完全にサポートし、豊富なモジュール解決戦略を提供します。
モジュールシステムにより、コードを再利用可能なユニットに分割し、コードの組織化と再利用を実現できます。
SVG 図解:モジュールのエクスポートとインポート
なぜモジュールシステムが必要か
プロジェクトの規模が大きくなるにつれて、コード量はますます増えていきます。
コードを複数のファイルに分散し、モジュールで整理することで、コードの保守性と再利用性を向上させることができます。
モジュールシステムにより、各ファイルが独自のスコープを持ち、グローバル変数の汚染を防ぎます。
概念の説明:モジュールとは、エクスポート文とインポート文を含む TypeScript ファイルです。export で内容をエクスポートし、import で内容をインポートします。
モジュールのエクスポート
export キーワードを使用すると、変数、関数、クラス、インターフェースなどをエクスポートして、他のモジュールで使用できるようにできます。
user.ts モジュール
export var name = "Alice";
export const age = 25;
// 関数のエクスポート
export function greet(message: string): string {
return "Hello, " + message;
}
// クラスのエクスポート
export class User {
// コンストラクタのパラメータプロパティ
constructor(public name: string) {}
// 自己紹介メソッド
introduce(): string {
return "I am " + this.name;
}
}
// インターフェースのエクスポート(インターフェースはコンパイル後に消え、型チェックにのみ使用されます)
export interface Config {
// ホストの設定
host: string;
// ポートの設定
port: number;
}
// 一括エクスポート:名前を変更してエクスポート
export { name as userName, age as userAge };
注意:インターフェースと型は、コンパイル後の JavaScript では実際のコードを生成しません。これらは TypeScript の型チェックにのみ使用されます。
モジュールのインポート
import キーワードを使用して、他のモジュールからエクスポートされた内容をインポートします。
main.ts でのモジュールのインポート
import { name, age, greet } from "./user";
// デフォルトインポート:モジュールのデフォルトエクスポートをインポート
import User from "./user";
// すべてインポート:モジュールのすべてのエクスポートを1つのオブジェクトにまとめる
import * as UserModule from "./user";
// 名前を変更してインポート:名前の衝突を回避
import { greet as sayHello } from "./user";
// インポートした内容を使用
console.log(greet("World"));
console.log(sayHello("TypeScript"));
実行結果:
Hello, World Hello, TypeScript
パスの説明:インポートパスは相対パス(例:
./user)または絶対パス(例:@/utils)。
デフォルトエクスポート
各モジュールはデフォルトエクスポートを1つ持つことができます。
デフォルトエクスポートはインポート時に波括弧を使用する必要がなく、任意の名前を付けることができます。
math.ts モジュール
export default function add(a: number, b: number): number {
return a + b;
}
// 他のエクスポートと組み合わせて使用できる
export function multiply(a: number, b: number): number {
return a * b;
}
main.ts のインポート
import add from "./math";
// 名前付きエクスポートのインポート:波括弧が必要
import { multiply } from "./math";
console.log("加算: " + add(2, 3));
console.log("乗算: " + multiply(4, 5));
実行結果:
加法: 5 乘法: 20
推奨事項:ユーティリティ関数やクラスなどの主要なエクスポートにはデフォルトエクスポートを使用し、補助関数やインターフェースなどには名前付きエクスポートを使用します。
再エクスポート
再エクスポート(Re-export)は、複数のモジュールの内容を集約したり、あるモジュールのエクスポートを別のモジュールに公開したりするために使用します。
index.ts のモジュール集約
export { name, age } from "./user";
// デフォルトエクスポートを再エクスポート(名前の変更が必要)
export { default as User } from "./user";
// すべての内容を再エクスポート
export * from "./math";
適用シナリオ:index.ts をエントリファイルとして使用し、サブモジュールの内容を一元的にエクスポートすることで、一括インポートが容易になります。
モジュール解決戦略
TypeScript は、インポートされたモジュールを検索するための複数のモジュール解決戦略を提供します。
tsconfig.json で設定できます。
tsconfig.json の設定
"compilerOptions": {
// Node 解決戦略
// Node.js のモジュール解決ルールに従う
"moduleResolution": "node",
// クラシック解決戦略
// TypeScript の初期バージョンで使用されていた戦略
"moduleResolution": "classic",
// base URL:ベースパスの設定
// すべての非相対パスインポートはこのパスに基づいて解決される
"baseUrl": "./src",
// パスマッピング:インポートパスにエイリアスを設定
"paths": {
// @ で始まるインポートは src ディレクトリにマッピング
"@/*": ["./*"],
// @components で始まるインポートは components ディレクトリにマッピング
"@components/*": ["./components/*"]
}
}
}
設定の推奨事項:新規プロジェクトでは Node 解決戦略の使用を推奨します。これは現在最も一般的な方法です。
動的インポート
動的インポート(Dynamic Import)は import() 構文を使用し、実行時に必要に応じてモジュールをロードできます。
これはコード分割や遅延ロードに非常に役立ちます。
例
// import() は Promise を返す
async function loadMath() {
// モジュールを動的インポート。この場所まで実行されたときだけロードされる
var math = await import("./math");
// math.default はデフォルトエクスポートされた関数
console.log("動的加算: " + math.default(1, 2));
}
// 遅延ロード関数を呼び出す
loadMath();
// 条件付きインポート:条件に応じて異なるモジュールを動的にロード
async function loadFeature(enable: boolean) {
if (enable) {
// 条件が満たされたときだけモジュールをロード
var feature = await import("./feature");
feature.run();
}
}
// 条件に応じてロード
loadFeature(true);
実行結果:
动态加法: 3
パフォーマンス最適化:動的インポートによりコード分割が可能になり、必要なときだけ追加のコードをロードして、初期ロード時間を短縮できます。
注意事項
- 相対パス:相対パスを使用してローカルモジュールをインポート(./、../)
- モジュールの拡張子:TypeScript はコンパイル時に拡張子を自動的に処理します
- デフォルト vs 名前付き:各モジュールに1つのデフォルトエクスポート、複数の名前付きエクスポート
- esModuleInterop:このオプションを有効にすると、CommonJS モジュールをより簡単にインポートできます
ベストプラクティス:インポートパスを一貫させ、パスエイリアスを使用して長いパスを簡素化し、明確なモジュール組織構造を確立します。
まとめ
モジュールシステムは TypeScript プロジェクト組織化の核です。
- export:変数、関数、クラス、インターフェースのエクスポート
- import:エクスポートされた内容のインポート
- デフォルトエクスポート:各モジュールに1つ、柔軟に使用可能
- 再エクスポート:モジュールの集約、エントリファイルの作成
- 動的インポート:遅延ロード、パフォーマンスの最適化
- モジュール解決:パスエイリアスと解決戦略の設定
その他の拡張推奨事項:モジュール構造を適切に整理し、パスエイリアスを使用してインポートを簡素化し、明確なエクスポート・インポート規約を確立します。