問題の概要
「Namespace has no exported member」エラーに直面することは、TypeScript開発者にとって避けて通れない道のようなものです。つい先ほどまで型定義が完璧に動作していたのに、突然VS Codeに赤い波線が表示され、ビルドが失敗することがあります。これは通常、確実に定義したはずの型やインターフェースにアクセスしようとしているのに、コンパイラがそれを見つけられない場合に発生します。
// エラー出力の例
error TS2694: Namespace 'MyProject' has no exported member 'UserConfig'.
根本原因の分析
コンパイラが意地悪をしているわけではありません。通常、以下のいずれかの理由で不一致が発生しています。
- exportキーワードの不足: ネームスペースはオブジェクトのように動作します。明示的に公開設定(export)にしない限り、内部の要素はすべてプライベートになります。
- モジュールの罠:
.d.tsファイル内にトップレベルのimportやexportが含まれていると、TypeScriptはそのファイルをグローバルスクリプトではなくESモジュールとして扱うようになり、グローバルなアクセスができなくなります。 - パスの設定ミス:
tsconfig.jsonファイルが、型宣言ファイルが置かれているフォルダを監視対象に含めていない可能性があります。
解決のためのステップ
方法 1:明示的なexportキーワードの追加
ネームスペースは「閉じた箱」のようなものだと考えてください。箱自体にアクセスできても、中のアイテムはデフォルトで隠されています。TypeScriptでは、ネームスペース内のメンバーの前にexportを付けない限り、それらはプライベートな扱いとなります。
types.d.tsファイルが以下のパターンになっていないか確認してください。
// ❌ 誤り:UserProfileはネームスペース内で非公開になっています
declare namespace API {
interface UserProfile {
id: string;
name: string;
}
}
// ✅ 正解:exportキーワードを付けることで外部から参照可能になります
declare namespace API {
export interface UserProfile {
id: string;
name: string;
}
}
方法 2:「モジュールの罠」への対処
宣言ファイルの冒頭に(import { AxiosResponse } from 'axios'のような)importを1つでも追加すると、大きな変化が起こります。TypeScriptはそのファイルをグローバルな型定義としてではなく、ESモジュールとして扱います。その結果、API.UserProfileをグローバルに直接使用する能力が失われます。
これを解決するには、ネームスペース自体をエクスポートし、必要な場所で個別にインポートする必要があります。
// types/AppTypes.ts
import { Request } from 'express';
export namespace AppTypes {
export interface Context extends Request {
userRole: 'admin' | 'user' | 'guest';
}
}
その後、他のモジュールと同じようにサービス内でインポートして使用します。
import { AppTypes } from './types/AppTypes';
const role: AppTypes.Context['userRole'] = 'admin';
方法 3:tsconfig.jsonのパス更新
コード自体は完璧でも、コンパイラが間違った場所を探していることがあります。プロジェクトに独自の型定義フォルダがある場合は、tsconfig.jsonがそれを認識しているか確認してください。include配列にsrc/**/*.d.tsを追加するのが、すべての宣言を確実に読み込ませる信頼できる方法です。
{
"compilerOptions": {
"typeRoots": ["./node_modules/@types", "./src/types"],
"baseUrl": ".",
"paths": {
"@types/*": ["src/types/*"]
}
},
"include": [
"src/**/*.ts",
"src/**/*.d.ts"
]
}
動作確認の手順
修正を適用したら、以下の3つのステップで正しく動作するか確認しましょう。
- TSサーバーの再起動: IDEが古いエラーをキャッシュしていることがあります。VS Codeでは、
Cmd+Shift+P(macOS) またはCtrl+Shift+P(Windows) を押し、「TypeScript: TS サーバーを再起動」を実行してください。 - ツールチップの確認: ネームスペースの上にマウスを置きます。正しく設定されていれば、エクスポートされたすべてのメンバーがリスト表示されます。
- ビルドの試行:
npx tsc --noEmitを実行します。これは、フルビルドを待たずに型エラーをチェックする最も速い方法です。
再発防止のアドバイス
- モジュールの優先: 最近のTypeScript開発では、ネームスペースよりもESモジュール(
import/export)の使用が推奨されます。依存関係が追跡しやすく、ツリーシェイキング(不要なコードの削除)にも適しています。 - ローカルに保つ: 1つのコンポーネントでしか使わない型は、そのファイル内で定義しましょう。グローバルな型は、共有データモデルやライブラリの設定用に予約しておくべきです。
- 名前の衝突に注意: ネームスペース名が変数名やクラス名と衝突していないか確認してください。これはコンパイラを混乱させる原因になります。

