TypeScriptモジュールと名前空間を完全解説!分割して管理する基本構文
生徒
「プログラムのコードが長くなってきて、どこに何が書いてあるか分からなくなってきました…。」
先生
「それは成長の証ですね!TypeScriptでは、ファイルを分割して整理する『モジュール』という仕組みを使います。」
生徒
「ファイルを分けても、別のファイルの内容を使うことはできるんですか?」
先生
「もちろんです。今回は、コードを綺麗に整理するための『モジュール』と『名前空間』の使い方を詳しく解説しますね!」
1. モジュールと名前空間とは?
TypeScriptを学習していくと、一つのファイルにたくさんのコードを書きがちです。しかし、数千行にもなるコードが一つのファイルにあると、後から修正するのがとても大変になります。そこで重要になるのが、「モジュール(Module)」と「名前空間(Namespace)」という考え方です。
モジュールとは、関連する機能ごとにファイルを分割する仕組みのことです。例えば、「計算に関する機能」「ユーザーの情報を扱う機能」「画面の表示を制御する機能」といった具合に、役割ごとにファイルを作成します。これにより、必要な時に必要な部品だけを呼び出して使うことができるようになります。
一方、名前空間は、コードの中で名前がぶつからないようにグループ分けをする仕組みです。例えるなら、名字のようなものです。同じ「太郎くん」でも「佐藤家の太郎くん」と「鈴木家の太郎くん」がいれば区別がつきますよね。プログラミングでも、同じ名前の関数や変数が登場した時に、この「家(グループ)」を分けることで混乱を防ぐのです。
現代の開発では「モジュール」を使うことが主流ですが、まずはこの「分ける」という感覚を身につけることが、脱・初心者への第一歩となります。
2. モジュールの基本:export(書き出し)
モジュールを使うためには、まず「他のファイルでも使いたい変数や関数」に対して、export(エクスポート)という命令を付ける必要があります。これは「この部品を外に公開しますよ」という宣言です。
パソコンを触ったことがない方でも、料理に例えると分かりやすいかもしれません。キッチン(ファイル)で作った料理(関数)を、食堂(別のファイル)に運ぶために「お盆に乗せる」作業がexportです。
具体的には、変数や関数の前に export と書くだけでOKです。
// mathUtils.ts という名前のファイルだとします
export const pi = 3.14;
export function calculateCircleArea(radius: number): number {
return pi * radius * radius;
}
このように書くことで、piという数字とcalculateCircleAreaという関数が、他のファイルから見える状態になります。
3. モジュールの基本:import(読み込み)
公開された部品を使う側では、import(インポート)という命令を使います。これは「外にある部品を自分のファイルに取り込む」という意味です。先ほどの料理の例なら、食堂側で「料理を受け取る」動作ですね。
構文は import { 取り出したい名前 } from "ファイルの場所" と書きます。
// main.ts という別のファイル
import { pi, calculateCircleArea } from "./mathUtils";
console.log(pi); // 3.14 と表示される
const area = calculateCircleArea(10);
console.log(area); // 314 と表示される
注意点: ファイルの場所を指定する際、./ は「同じフォルダ内」を意味します。また、TypeScriptでは読み込み時に .ts という拡張子は書かないのが一般的です。
4. デフォルトエクスポート(export default)
モジュールには、そのファイルで「メインとなる部品」を一つだけ決めて書き出すexport defaultという方法があります。これを使うと、読み込む側で名前を自由につけることができ、さらに { }(波括弧)を使わずに書けるというメリットがあります。
// Message.ts
export default class Message {
sayHello() {
console.log("こんにちは!");
}
}
読み込むときは以下のようになります。
// app.ts
import MyMessage from "./Message";
const msg = new MyMessage();
msg.sayHello();
実行結果は以下の通りです。
こんにちは!
export default で書き出したものは、読み込む側で MyMessage のように好きな名前を付けることができるため、非常に柔軟です。ただし、一つのファイルに一つしか作れないというルールがあります。
5. 名前空間(Namespace)の使い方
次に、モジュールとは少し異なる名前空間(Namespace)について学びましょう。名前空間は、一つのファイル内、あるいは複数のファイルにまたがって「論理的なグループ」を作るために使われます。最近のWeb開発ではモジュールが主流ですが、古いプログラムのメンテナンスや、特定のライブラリ作成では今でも使われることがあります。
名前空間を定義するには namespace 名前 { ... } と記述します。その中にあるものを外から使えるようにするには、やはり export が必要です。
namespace MyTools {
export const version = "1.0.0";
export function log(msg: string) {
console.log("ログ: " + msg);
}
}
// 使うときは「名前空間名.プロパティ名」で呼び出します
console.log(MyTools.version);
MyTools.log("システム起動");
実行結果は以下の通りです。
1.0.0
ログ: システム起動
このように、MyTools という箱の中にデータや機能を詰め込むイメージです。これにより、他の場所で version という変数をうっかり作ってしまっても、MyTools.version とは別物として扱われるので安心です。
6. モジュールと名前空間の使い分け
「どっちを使えばいいの?」と迷うかもしれません。初心者の方は、まず「モジュール(import/export)」を優先的に覚えましょう。
理由は、現在のプログラミングの世界では「1つのファイル = 1つのモジュール」として扱うのが標準的だからです。名前空間は、ファイルを分けずにグループ化したい時や、非常に大規模なシステムで名前の衝突を絶対に避けたい時に補助的に使われることが多いです。
パソコン操作に慣れていない方にとって、「ファイルを分ける」というのは少しハードルが高く感じるかもしれません。しかし、デスクトップにファイルをバラバラに置くよりも、フォルダ(モジュール)に整理して片付ける方が、後で探しやすくなるのと同じだと考えてください。
7. 実践:複数のファイルを組み合わせてみよう
最後に、より実践的な例を見てみましょう。ユーザーの情報を管理するモジュールを作ってみます。
まず、ユーザーの型(形)を定義するファイルです。
// types.ts
export interface User {
id: number;
name: string;
}
次に、そのユーザーを表示する機能を持つファイルです。
// display.ts
import { User } from "./types";
export function showUser(user: User) {
console.log("ID:" + user.id + " 名前:" + user.name);
}
最後に、これらを呼び出すメインのファイルです。
// main.ts
import { User } from "./types";
import { showUser } from "./display";
const me: User = { id: 1, name: "たろう" };
showUser(me);
実行結果は以下の通りです。
ID:1 名前:たろう
このように、役割ごとにファイルを分けることで、どこに何が書いてあるかが一目で分かるようになります。これが、TypeScriptにおける保守性の高い(メンテナンスしやすい)プログラムの作り方です。
8. よくあるエラーと対処法
モジュールを使い始めると、いくつか特有のエラーに遭遇することがあります。代表的なものを紹介します。
①「Cannot find module './xxx'」
これは、指定した場所にファイルが見つからないというエラーです。ファイル名が間違っていないか、./ を忘れていないか確認しましょう。
②「...is not exported」
これは、使いたい変数や関数に export が付いていない時に起こります。お盆に乗せていない料理は食堂には運べません。しっかり export を書き足しましょう。
③ 波括弧 { } の有無
export const などで書き出した場合は import { name } と波括弧が必要です。一方で export default の場合は波括弧は不要です。この違いは間違いやすいポイントなので、何度も書いて慣れていきましょう。
TypeScriptのモジュールと名前空間を理解することは、大規模な開発への第一歩です。最初は「ファイルを分けるのが面倒くさい」と感じるかもしれませんが、コードが増えてきた時にその便利さを実感できるはずです。まずは小さなプログラムから、役割ごとにファイルを分ける練習をしてみてくださいね。