なぜ今、`isolatedModules` をオンにすべきなのか?——「コンパイルの罠」を回避するプロの作法
現場でコードを書いていると、ふと遭遇する「TypeScriptの型チェックは通るのに、なぜか実行時にエラーが出る」という現象。これ、実はビルドツールとの「見解の相違」が原因であることが多いんです。
特に最近のフロントエンド開発において、`tsc`(TypeScript公式コンパイラ)を単体で動かすことは稀です。多くの場合、`esbuild` や `Babel`、あるいは `SWC` といった高速なツールがトランスパイル(JSへの変換)を担っています。
ここで重要な役割を果たすのが、`tsconfig.json` の設定項目の一つ、`”isolatedModules”: true` です。今日は、なぜこれが単なる設定項目以上の意味を持つのか、現場の視点から紐解いていきましょう。
—
「型のみのインポート」が引き起こす悲劇
まず、なぜ `isolatedModules` が必要なのか。最大の理由は、「Babelやesbuildは、ファイルの型情報を知らないから」です。
`tsc` はプロジェクト全体を解析して型を評価しますが、Babelなどは基本的に「今開いているそのファイルだけ」を変換します。もし、あるファイルが「型定義だけ」をインポートしていて、それが実行時に消滅してしまうような書き方をしていると、Babelなどの単一ファイル変換ツールは「このインポートは何のためのもの?」と混乱し、最終的な出力コードで挙動不審になることがあります。
`isolatedModules: true` を設定すると、TypeScriptは「他のファイルを参照しないと解決できない構文」を禁止してくれます。これにより、「どのツールで変換しても同じ結果が得られる」という移植性(ポータビリティ)が担保されるのです。
—
実践:`isolatedModules` が検知する「ダメなコード」
具体的に、どのようなコードがNGになるのかを見てみましょう。これを書くと `tsc` が即座に怒ってくれるようになります。
// 1. 名前空間(Namespace)の非推奨利用
// Babelなどはファイル単位で処理するため、別ファイルのNamespaceを跨ぐような参照はNG
namespace MyModule {
export const value = 1;
}
export default MyModule;
// 2. 「型のみ」のインポートの曖昧さ
// これが isolatedModules でエラーになる典型例。
// コンパイラは「これ、実行時に必要なコードなの?それとも型だけ?」という判断を、
// そのファイル単体で見極められないと困るのです。
import { SomeType } from ‘./types’; // もしこれが型定義だけなら…
const x: SomeType = 1; // ここでエラーになります
こう書き換えるのが現場のベストプラクティス
`isolatedModules` をオンにした状態で、モダンかつ安全に書くための書き方はこちらです。
/
- 【改善策】
- 型のみをインポートする場合は ‘type’ 修飾子を付ける。
- これにより、トランスパイラは「あ、これは実行時には消していいやつね」と
- 即座に判断できるため、変換の失敗がなくなります。
/
import type { SomeType } from ‘./types’;
// 名前空間は卒業して、ES Modules(export/import)に統一しましょう。
// 名前空間は構造的な重複を招きやすく、バンドラーとの相性も最悪です。
export const value = 1;
// 構造化された型定義
export interface User {
id: number;
name: string;
}
—
ブラウザの裏側で起きていること
ブラウザはTypeScriptを直接実行できません。必ずJavaScriptに変換される必要があります。
`isolatedModules` を有効にすると、TypeScriptは「このファイルは、他のファイルの影響を一切受けずに、単体でJavaScriptに変換できるか?」という厳しい検査を行います。これが有効であれば、あなたのコードは `esbuild` で爆速ビルドしようが、`Babel` でレガシーなブラウザ向けに変換しようが、「変換後のJSコードの挙動」が安定するという強力な保証が得られます。
「設定一つでビルド時間が変わるわけではないけれど、ビルドの『再現性』が劇的に上がる」——これこそが、シニアエンジニアが `tsconfig.json` にこの設定を刻み込む理由です。
—
まとめ:今日から始める設定
まずは、あなたのプロジェクトの `tsconfig.json` を開いてみてください。
{
“compilerOptions”: {
// 必須設定。モダンなフロントエンド開発の最低条件です
“isolatedModules”: true,
// 合わせて設定すべき推奨オプション
“esModuleInterop”: true,
“skipLibCheck”: true
}
}
もし今、`isolatedModules` が `false` になっているなら、恐る恐る `true` にしてみてください。おそらく、いくつか「今まで曖昧に動いていた」箇所で型エラーが出るはずです。そのエラーこそが、あなたのコードをより堅牢にするための招待状です。
一つずつ修正していく過程で、あなたのTypeScriptへの理解は確実に一段上のレベルへと引き上げられます。現場の混乱を未然に防ぐため、ぜひ今日から取り入れてみてください。
それでは、良いコーディングライフを!

コメント