import/export モジュールとエクスポート(CommonJS との相互運用を含む)

最終更新:2026-10-23

import/export モジュールとエクスポート(CommonJS との相互運用を含む)

ES Modules は JavaScript の公式のモジュール標準です。TypeScript は export/import の構文をそのまま使い、「型」もモジュールシステムに組み込みました。型はエクスポート・インポートでき、import type は型だけをインポートし、コンパイル後には完全に消えます。バレルファイル(barrel、通常は index.ts)は複数のモジュールをまとめて再エクスポートし、外部には1つの import の入口だけを提供します。CommonJS との相互運用は module / esModuleInterop などのコンパイラオプションで決まります。

グループ設定と実践
種類構文
strict モード不要

ℹ️ 説明 エディタは TypeScript を JavaScript にトランスパイルして実行します(型チェックなし)。型チェック結果は各サンプルの出力を参照してください。

📝 構文

// エクスポート
export interface User { id: number; name: string }  // 型をエクスポート
export const add = (a: number, b: number) => a + b; // 値をエクスポート
export default function greet() {}                  // デフォルトエクスポート

// インポート
import greet, { add } from "./math";  // デフォルト + 名前付き
import type { User } from "./types";  // 型のみ、コンパイル後に消える
export * from "./math";               // バレル再エクスポート

⚙️ パラメータ

export defaultモジュールの「既定の出口」です。各モジュールに最大1つ。import するときは任意の名前を使え、波括弧は不要です
export * from / re-exportバレルファイルの中核の書き方です。サブモジュールのすべての名前付きエクスポートを転送し、import type の型も転送されます
import type / inline typeimport type { User } と import { type User }(インライン修飾子)は等価で、どちらも「型だけをインポートする」と宣言し、コンパイル後には実行時コードを一切残しません

戻り値:モジュール自体に戻り値はありません。export された値と型が合わさってモジュールの公開インターフェースを構成し、他のモジュールが import します。

▶ サンプル

下のコードを編集して「試す」を押すと、トランスパイル実行結果を確認できます:

出力:

Hello, Ada!
add === add2: true

(トランスパイル後の実行出力。このエディタはブラウザ内のインラインスクリプトで動作するため、実際にファイル跨ぎの import は使えません。上のコードはモジュール境界をコメントで示し、等価な実行可能な形で演示しています。実際のプロジェクトでは(types.ts / math.ts / utils.ts / main.ts)の4つの別ファイルのままです。User は純粋な型で、import type はコンパイル後に痕跡を残しません)

💡 ポイント

ℹ️ 説明 import type と通常の import で同名の型を取り込む効果は同じですが、import type の方が意味が明確で、isolatedModules の下でも安全に使えます。コンパイル後はどちらも型の部分が消えます。
💡 ヒント バレルファイルは src のルートに置き(index.ts)、中身は export * from / export { x } from の行だけにします。呼び出し側は @/utils/math のような深いパスではなく @/utils と書け、ディレクトリ構造の再編時に触るのはバレルだけです。
⚠️ 注意 CommonJS との相互運用は事故の多発地帯です。TS がコンパイルした CJS では、import default と module.exports の対応関係で間違いやすいのです。esModuleInterop を有効にし(module: commonjs と併用)て初めて挙動が ES の仕様と一致します。さらに module を node16/nodenext にしたときは、相対 import に拡張子まで書くことが要求されます。
ケースは今後追加予定です。

📚 関連チュートリアル

❓ よくある質問

Q import type と普通の import の違いは何ですか?
A 普通の import は、型しか使っていなくても require の呼び出しにコンパイルされることがあります。import type は「型だけのインポート」を保証し、実行時コードを一切生成しません。isolatedModules の下やバンドラの tree-shaking の場面では、「型のためだけにパッケージ全体を残す」問題を避けられます。
Q どんなときにバレルファイルを作る価値がありますか?
A あるディレクトリが外部に公開するモジュールが3〜4個を超え、呼び出し側がそのうちの複数を同時に import することが多いときです。ただしバレルはすべてのサブモジュールを同じ依存グラフに入れるため、バンドラの tree-shaking に影響するかもしれません。純粋なユーティリティライブラリなら作ってよいですが、コンポーネントが多くサイズが気になる場面では評価が必要です。
Q 実行時に "Cannot use import statement outside a module" が出るのはなぜですか?
A 実行環境が ESM の構文を理解していないからです。成果物の中の import が変換されていない(target が新しすぎるか module の設定が間違っている)か、Node が .js を CJS として実行しています。解決は、module を commonjs にする(またはバンドラに ESM を処理させる)、ESM のファイルを .mjs にする、または package.json に "type": "module" を宣言する、のいずれかです。
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%