TypeScriptのモジュールと名前空間を完全ガイド!複数プロジェクトでコードを再利用する仕組み
生徒
「TypeScriptで、一度作った便利なプログラムを他のプロジェクトでも使い回す方法ってありますか?」
先生
「はい、もちろんです!TypeScriptには『モジュール』という仕組みがあって、それを使うと部品のようにプログラムを切り出して再利用できるんですよ。」
生徒
「部品みたいに、ですか?具体的にはどうやってファイルを分けたり、つなげたりするんですか?」
先生
「それでは、モジュールの基本から、複数のプロジェクトで再利用する設計のコツまで詳しく見ていきましょう!」
1. モジュールと名前空間とは?
プログラミングをしていると、コードがどんどん長くなって、どこに何が書いてあるか分からなくなることがあります。これを解決するのが「モジュール(Module)」と「名前空間(Namespace)」です。
パソコンを触ったことがない方に例えるなら、モジュールは「引き出し」のようなものです。文房具は文房具の引き出しに、書類は書類の引き出しに分けて入れておけば、必要なときにすぐに取り出せますよね。
モジュールは、関連する機能(関数やクラスなど)を一つのファイルにまとめ、他のファイルから呼び出せるようにする仕組みです。現代のTypeScript開発では、この「モジュール」が主流です。
一方、名前空間は、一つの大きな箱の中に仕切りを作るイメージです。昔のプログラムでよく使われていましたが、現在は特別な理由がない限りモジュールを使うのが一般的です。
2. モジュールの基本的な使い方(exportとimport)
TypeScriptでコードを再利用する第一歩は、「出す(export)」と「入れる(import)」を覚えることです。
ファイルを外に出す「export」
他のファイルで使いたい関数や変数の前に export というキーワードをつけます。これは「この部品は外で使ってもいいですよ」という許可証のようなものです。
// mathUtils.ts というファイル
export const add = (a: number, b: number): number => {
return a + b;
};
export const subtract = (a: number, b: number): number => {
return a - b;
};
ファイルを読み込む「import」
外に出された部品を使いたいときは、import を使います。
// app.ts というファイル
import { add, subtract } from "./mathUtils";
console.log(add(10, 5));
console.log(subtract(10, 5));
実行結果は以下のようになります。
15
5
3. 名前空間(Namespace)の役割
名前空間は、プログラムの中で名前がぶつからないようにするための仕切りです。例えば、「佐藤さん」という名前の人がクラスに二人いたら混乱しますよね?「1組の佐藤さん」「2組の佐藤さん」と分けることで、区別がつくようになります。
TypeScriptでも、同じ「Calculator」という名前のプログラムが複数あっても、名前空間を使えば衝突を避けられます。
namespace School {
export class Student {
name: string = "太郎";
}
}
let student = new School.Student();
console.log(student.name);
実行結果:
太郎
4. 複数プロジェクトで再利用する仕組み
さて、本題の「複数のプロジェクトでコードを使い回す」方法について解説します。これには主に3つの方法があります。
① npmパッケージとして公開する
npmとは、世界中の人が作ったTypeScriptやJavaScriptの部品が保存されている巨大な倉庫のようなものです。自作した便利な機能をこの倉庫に登録(公開)すると、自分の他のプロジェクトだけでなく、世界中の人があなたのコードを使えるようになります。
非公開にしたい場合は、会社内だけで使えるプライベートな倉庫を作ることも可能です。
② Git(ギット)サブモジュールを使う
Gitは、プログラムの変更履歴を記録するツールです。サブモジュールという機能を使うと、あるプロジェクトの中に、別のプロジェクトのプログラムを「リンク」として埋め込むことができます。
③ モノレポ(Monorepo)構成にする
最近の流行りは「モノレポ」です。これは、一つの大きなフォルダの中に、複数のプロジェクトをまとめて管理する方法です。 例えば、以下のような構造になります。
- packages/shared(共通の計算ルールなど)
- packages/website(公式サイトのプログラム)
- packages/admin-app(管理者用アプリのプログラム)
この構成にすると、shared に書いたコードを、website と admin-app の両方から簡単に呼び出すことができます。
5. 再利用しやすいコード設計のコツ
ただファイルを分けるだけでは、使いにくいコードになってしまいます。再利用性を高めるためのポイントを3つ紹介します。
依存関係をシンプルにする
「この計算機能を使うには、あの画面のデザイン機能も必要」という状態(依存している状態)だと、他のプロジェクトに持っていくのが大変です。 再利用したい部分は、他の機能に頼らなくても単独で動くように作りましょう。
インターフェースを活用する
以前の学習で出てきた「インターフェース」を使い、「どんなデータが必要か」というルールだけを先に決めておきます。これにより、中身のプログラムが少し変わっても、使う側は影響を受けにくくなります。
ドキュメントを残す
半年後の自分がそのコードを見たとき、「これってどうやって使うんだっけ?」とならないように、コメントをしっかり書きましょう。TypeScriptなら、型を定義するだけで、それが最高の説明書になります。
6. 実践:共通モジュールを作ってみよう
実際に、ユーザーの名前を整形する「共通部品」をイメージしてみましょう。
// userLibrary.ts (共有したいライブラリ)
export interface User {
firstName: string;
lastName: string;
}
export function getFullName(user: User): string {
return `${user.lastName} ${user.firstName}`;
}
この userLibrary.ts を一つのファイルとして保存しておけば、Webサイトを作るときも、スマホアプリを作るときも、全く同じコードをコピーせずに使い回すことができます。
7. プログラミング初心者が気をつけるべきこと
パソコンの操作に慣れていない方は、ファイルの「保存場所(パス)」に注意しましょう。
import { ... } from "./utils" の ./ は、「今自分がいる場所と同じフォルダ」という意味です。
ファイルが見つからないというエラーが出たときは、まず「ファイルの住所(パス)」が合っているか確認してみてください。
また、モジュールを分けるときは「1ファイル1機能」を意識すると、後で探しやすくなります。大きすぎる引き出しは何でも入っていて便利そうですが、中身がぐちゃぐちゃになりやすいのと同じです。
8. TypeScriptモジュール設計の重要性
なぜここまでして細かく分けるのでしょうか?それは、大規模な開発になればなるほど、一人で全てのコードを管理できなくなるからです。
モジュール化がしっかりできていると、Aさんは「ログイン機能」、Bさんは「商品検索機能」というように、作業を分担しやすくなります。そして、それぞれが作ったモジュールを最後にガッチャンコと組み合わせることで、一つの大きなシステムが出来上がります。
この「分ける」技術こそが、プログラミングの上達において非常に重要なステップとなります。