ESLint × TypeScript「Parsing error: Cannot read file 'tsconfig.json'」完全解決ガイド
TypeScript プロジェクトで ESLint を設定した際に、「Parsing error: Cannot read file 'tsconfig.json'」というエラーに遭遇したことはありませんか。このエラーは、ESLint が TypeScript の設定ファイルを正しく読み込めない場合に発生します。
特に、モノレポ構成や Next.js プロジェクトなど、複数の tsconfig.json ファイルが存在する環境では頻繁に遭遇するエラーです。本記事では、このエラーの原因から具体的な解決方法まで、初心者の方にもわかりやすく解説していきますね。
背景
ESLint と TypeScript の連携の仕組み
ESLint で TypeScript のコードを解析するには、@typescript-eslint/parserというパーサーを使用します。このパーサーは、TypeScript のコンパイラ(TypeScript Compiler API)を内部で利用しており、型情報を含めた高度な静的解析を実現しています。
型情報を活用することで、単純な構文チェックだけでなく、型安全性に関わるルールも適用できるようになります。これが TypeScript と ESLint を組み合わせる大きなメリットですね。
tsconfig.json の役割
tsconfig.jsonは、TypeScript コンパイラの設定ファイルです。このファイルには、以下のような重要な情報が含まれています。
typescript{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true,
"esModuleInterop": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
@typescript-eslint/parserは、この設定ファイルを読み込むことで、プロジェクトの TypeScript 環境を正しく理解します。どのファイルが解析対象なのか、どのような型チェックルールが適用されているのかを把握できるのです。
以下の図は、ESLint が TypeScript コードを解析する際のデータフローを示しています。
mermaidflowchart LR
code["TypeScriptコード"] -->|読み込み| eslint["ESLint"]
eslint -->|解析依頼| parser["@typescript-eslint/parser"]
parser -->|設定読み込み| tsconfig["tsconfig.json"]
parser -->|型情報取得| tsapi["TypeScript Compiler API"]
tsapi -->|解析結果| parser
parser -->|AST| eslint
eslint -->|検証| rules["ESLintルール"]
rules -->|結果| output["エラー/警告"]
図から分かるように、tsconfig.jsonは TypeScript 解析の核となる設定ファイルです。このファイルが正しく読み込めないと、ESLint は適切な型情報を取得できず、エラーが発生してしまいます。
課題
エラーの詳細
このエラーが発生すると、以下のようなメッセージが表示されます。
textParsing error: Cannot read file 'tsconfig.json'
より詳細なエラーメッセージでは、以下のような内容が含まれることもあります。
textParsing error: Cannot read file '/path/to/your/project/tsconfig.json'.
Error: ENOENT: no such file or directory, open '/path/to/your/project/tsconfig.json'
このエラーには、主に以下のようなバリエーションがあります。
| # | エラーパターン | 意味 |
|---|---|---|
| 1 | ENOENT: no such file or directory | 指定されたパスにファイルが存在しない |
| 2 | Cannot read property of undefined | tsconfig.json のパス解決が失敗している |
| 3 | The file does not match your project config | tsconfig.json の include 設定に該当しない |
エラーが発生する主な原因
このエラーは、以下のような状況で発生しやすいです。
ESLint 設定ファイルでのパス指定ミス
.eslintrc.jsや.eslintrc.json内で、parserOptions.projectに指定したパスが間違っている場合です。相対パスの基準点を誤解していることが多いですね。
作業ディレクトリとの不一致 ESLint を実行する際の作業ディレクトリと、設定ファイルで想定しているディレクトリが異なる場合に発生します。これはモノレポ構成で特に起こりやすい問題です。
複数の tsconfig.json ファイルの管理
プロジェクト内に複数のtsconfig.jsonファイル(例:tsconfig.json、tsconfig.eslint.json、tsconfig.build.json)が存在し、正しいファイルを参照できていない場合です。
以下の図は、エラーが発生する典型的な状況を示しています。
mermaidflowchart TD
start["ESLint実行"] --> check["tsconfig.jsonを<br/>探す"]
check --> path1{".eslintrc.jsの<br/>project設定"}
path1 -->|相対パス| resolve["パス解決"]
resolve --> exists{ファイル<br/>存在?}
exists -->|はい| success["解析成功"]
exists -->|いいえ| error["Parsing error:<br/>Cannot read file"]
path1 -->|未設定| auto["自動検出"]
auto --> autoexists{ファイル<br/>存在?}
autoexists -->|はい| success
autoexists -->|いいえ| error
このように、パスの解決プロセスのどこかで失敗すると、エラーが発生してしまいます。
解決策
基本的な解決アプローチ
エラーを解決するには、ESLint が tsconfig.json を正しく見つけられるようにする必要があります。以下では、段階的に解決方法を説明していきますね。
解決方法 1:parserOptions.project の設定を確認
最も基本的な解決方法は、.eslintrc.js(または.eslintrc.json)のparserOptions.project設定を正しく指定することです。
まず、現在の設定を確認しましょう。
javascript// .eslintrc.js
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json', // この行を確認
},
// その他の設定...
};
このprojectの値は、ESLint 設定ファイル(.eslintrc.js)からの相対パスとして解釈されます。もし.eslintrc.jsがプロジェクトルートにあり、tsconfig.jsonも同じ場所にある場合は、以下のように指定します。
javascriptparserOptions: {
project: './tsconfig.json',
}
もしモノレポ構成で、ESLint 設定ファイルと tsconfig.json が異なるディレクトリにある場合は、適切な相対パスを指定してください。
javascript// packages/app/.eslintrc.js の場合
parserOptions: {
project: './tsconfig.json', // packages/app/tsconfig.json を指す
}
解決方法 2:絶対パスを使用する
相対パスの解決が複雑な場合は、絶対パスを使用すると確実です。Node.js のpathモジュールを活用しましょう。
javascript// .eslintrc.js
const path = require('path');
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: path.resolve(__dirname, './tsconfig.json'),
},
// その他の設定...
};
__dirnameは、.eslintrc.jsファイルが存在するディレクトリの絶対パスを表します。path.resolve()を使用することで、確実に正しいパスを生成できますね。
複数の tsconfig.json ファイルがある場合は、配列で指定することも可能です。
javascriptparserOptions: {
project: [
path.resolve(__dirname, './tsconfig.json'),
path.resolve(__dirname, './tsconfig.eslint.json'),
],
}
解決方法 3:tsconfigRootDir オプションを使用する
tsconfigRootDirオプションを使用すると、tsconfig.json の検索基準ディレクトリを明示的に指定できます。これはモノレポ構成で特に有効です。
javascript// .eslintrc.js
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig.json'],
},
// その他の設定...
};
tsconfigRootDirを設定すると、projectで指定されたパスは、このディレクトリからの相対パスとして解釈されます。これにより、パス解決の曖昧さがなくなりますね。
解決方法 4:tsconfig.eslint.json を作成する
プロジェクトの構成が複雑な場合、ESLint 専用のtsconfig.eslint.jsonを作成すると管理が楽になります。
まず、プロジェクトルートにtsconfig.eslint.jsonを作成します。
json{
"extends": "./tsconfig.json",
"include": ["src/**/*", "tests/**/*", ".eslintrc.js"]
}
ここでは、元のtsconfig.jsonを継承しつつ、ESLint で解析したいファイルをincludeで明示的に指定しています。.eslintrc.js自体も TypeScript で型チェックしたい場合は含めると良いでしょう。
次に、ESLint 設定でこのファイルを参照します。
javascript// .eslintrc.js
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.eslint.json',
},
// その他の設定...
};
この方法のメリットは、ビルド用の設定と Lint 用の設定を分離できることです。ビルド時には不要なテストファイルなども、Lint 対象に含めることができますね。
解決方法 5:ignorePatterns 設定を活用する
ESLint で解析する必要のないファイルは、ignorePatternsで除外することで、tsconfig.json との不整合を防げます。
javascript// .eslintrc.js
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json',
},
ignorePatterns: [
'node_modules/',
'dist/',
'build/',
'*.config.js',
],
// その他の設定...
};
ignorePatternsに指定されたファイルは、ESLint の解析対象から除外されます。これにより、tsconfig.json のincludeやexclude設定と矛盾することを防げます。
解決方法 6:createDefaultProgram を使用する(非推奨だが有効)
型情報を必要としないルールのみを使用している場合、createDefaultProgramオプションを有効にすることで、tsconfig.json が見つからない場合でもエラーを回避できます。
javascript// .eslintrc.js
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json',
createDefaultProgram: true, // 非推奨
},
// その他の設定...
};
ただし、このオプションは非推奨です。パフォーマンスが低下し、型情報を必要とするルールが正しく動作しない可能性があります。一時的な回避策としてのみ使用し、根本的な解決を目指しましょう。
具体例
ケース 1:Next.js プロジェクトでの設定
Next.js プロジェクトでは、複数の tsconfig.json ファイルが存在することが一般的です。以下は、典型的なディレクトリ構造です。
textmy-next-app/
├── .eslintrc.js
├── tsconfig.json
├── next.config.js
├── src/
│ └── app/
│ └── page.tsx
└── package.json
このような構造の場合、以下のように ESLint を設定します。
javascript// .eslintrc.js
const path = require('path');
module.exports = {
extends: [
'next/core-web-vitals',
'plugin:@typescript-eslint/recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
tsconfigRootDir: __dirname,
project: './tsconfig.json',
},
plugins: ['@typescript-eslint'],
ignorePatterns: [
'node_modules/',
'.next/',
'out/',
'next.config.js',
],
};
以下は、Next.js プロジェクトでの ESLint 設定の構造を示した図です。
mermaidflowchart TD
eslintrc[".eslintrc.js"] -->|参照| tsconfig["tsconfig.json"]
eslintrc -->|除外設定| ignore["ignorePatterns"]
tsconfig -->|include| src["src/**/*"]
ignore -->|除外| next[".next/"]
ignore -->|除外| modules["node_modules/"]
src -->|解析対象| components["コンポーネント"]
components -->|Lint実行| result["検証結果"]
重要なポイント:
tsconfigRootDir: __dirnameでパス解決の基準を明確化ignorePatternsでビルド成果物を除外- Next.js の推奨設定
next/core-web-vitalsを継承
ケース 2:モノレポ(Yarn Workspaces)での設定
モノレポ構成では、各パッケージごとに ESLint 設定と tsconfig.json を管理するのが一般的です。
textmonorepo/
├── .eslintrc.js (ルート設定)
├── tsconfig.json (ルート設定)
├── packages/
│ ├── web/
│ │ ├── .eslintrc.js
│ │ ├── tsconfig.json
│ │ └── src/
│ └── api/
│ ├── .eslintrc.js
│ ├── tsconfig.json
│ └── src/
└── package.json
ルートの設定ファイルは、共通設定として機能させます。
javascript// monorepo/.eslintrc.js (ルート)
module.exports = {
root: true, // ルート設定であることを明示
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
],
};
各パッケージでは、ルート設定を継承しつつ、独自の tsconfig.json を指定します。
javascript// packages/web/.eslintrc.js
const path = require('path');
module.exports = {
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.json',
},
// このパッケージ固有のルール
rules: {
'@typescript-eslint/no-unused-vars': 'error',
},
};
同様に、apiパッケージでも設定します。
javascript// packages/api/.eslintrc.js
const path = require('path');
module.exports = {
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.json',
},
rules: {
'@typescript-eslint/explicit-function-return-type':
'warn',
},
};
ポイント:
- ルートに
root: trueを設定し、設定の継承を制御 - 各パッケージで
tsconfigRootDir: __dirnameを使用 - パッケージごとに異なる tsconfig.json を参照可能
ケース 3:テストファイルを含む設定
テストファイルは、本番コードとは異なる tsconfig 設定を使いたい場合があります。以下のような構造を考えてみましょう。
textproject/
├── .eslintrc.js
├── tsconfig.json
├── tsconfig.test.json
├── src/
│ └── index.ts
└── tests/
└── index.test.ts
まず、tsconfig.test.jsonを作成します。
json{
"extends": "./tsconfig.json",
"compilerOptions": {
"types": ["jest", "node"]
},
"include": ["tests/**/*", "src/**/*"]
}
次に、ESLint 設定で複数の tsconfig.json を指定します。
javascript// .eslintrc.js
const path = require('path');
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig.json', './tsconfig.test.json'],
},
overrides: [
{
// テストファイル専用の設定
files: ['tests/**/*.test.ts'],
env: {
jest: true,
},
rules: {
'@typescript-eslint/no-explicit-any': 'off',
},
},
],
};
overridesを使用することで、テストファイルには異なるルールを適用できます。これにより、テストコードでの柔軟性を保ちつつ、本番コードの厳格性も維持できますね。
ケース 4:エディタ統合での問題解決
VS Code などのエディタでは、ESLint プラグインがバックグラウンドで動作します。この場合、ワークスペースのルートディレクトリが重要になります。
VS Code の設定ファイル(.vscode/settings.json)で、ESLint の作業ディレクトリを明示的に指定できます。
json{
"eslint.workingDirectories": [
{
"mode": "auto"
}
],
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
]
}
モノレポの場合は、各パッケージを個別に指定することもできます。
json{
"eslint.workingDirectories": [
"./packages/web",
"./packages/api"
]
}
これにより、エディタ上での ESLint エラーも正しく表示されるようになります。
ケース 5:トラブルシューティング手順
エラーが解決しない場合は、以下の手順で原因を特定しましょう。
ステップ 1:パスの確認
ESLint 設定ファイルにログ出力を追加して、パスを確認します。
javascript// .eslintrc.js
const path = require('path');
const tsconfigPath = path.resolve(
__dirname,
'./tsconfig.json'
);
console.log('tsconfig.json path:', tsconfigPath);
console.log(
'File exists:',
require('fs').existsSync(tsconfigPath)
);
module.exports = {
// 設定...
};
ステップ 2:TSConfig の検証
tsconfig.json の構文が正しいか確認します。
bashyarn tsc --noEmit
構文エラーがある場合、このコマンドでエラーが表示されます。
ステップ 3:ESLint のキャッシュクリア
ESLint のキャッシュが原因で問題が発生している可能性があります。
bashyarn eslint --clear-cache
キャッシュをクリアしてから、再度 ESLint を実行してみましょう。
ステップ 4:依存関係の確認
必要なパッケージが正しくインストールされているか確認します。
bashyarn list --pattern "@typescript-eslint"
以下のパッケージが必要です。
json{
"devDependencies": {
"@typescript-eslint/parser": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"eslint": "^8.0.0",
"typescript": "^5.0.0"
}
}
バージョンの互換性も重要です。@typescript-eslint/parserと@typescript-eslint/eslint-pluginは、同じバージョンを使用しましょう。
まとめ
「Parsing error: Cannot read file 'tsconfig.json'」エラーは、ESLint が TypeScript の設定ファイルを正しく読み込めない場合に発生します。このエラーを解決するための重要なポイントをまとめます。
基本的な解決アプローチ
.eslintrc.jsのparserOptions.project設定を正しく指定することが最も重要です。相対パスの基準点を理解し、必要に応じてtsconfigRootDirオプションを使用しましょう。
環境に応じた設定
Next.js プロジェクト、モノレポ構成、テストファイルを含む構成など、プロジェクトの特性に応じて適切な設定方法を選択してください。複雑な構成の場合は、tsconfig.eslint.jsonを作成して管理を分離すると良いですね。
トラブルシューティング
エラーが解決しない場合は、パスの確認、TSConfig の検証、キャッシュクリア、依存関係の確認を順番に実施してください。console.logでパスを出力することで、問題の原因を特定しやすくなります。
パフォーマンスとメンテナンス性
createDefaultProgramオプションは非推奨なので、根本的な解決を目指しましょう。また、ignorePatternsを適切に設定することで、不要なファイルの解析を避け、パフォーマンスを向上できます。
TypeScript と ESLint の組み合わせは、型安全性とコード品質の両方を高める強力なツールです。正しく設定することで、開発体験が大きく向上しますので、ぜひこの記事を参考に設定を見直してみてください。
関連リンク
articleESLint × TypeScript「Parsing error: Cannot read file 'tsconfig.json'」完全解決ガイド
articleESLint と AST 入門:ESTree/Token/SourceCode を 10 分で把握
articleESLint 変更管理と段階リリース:CI のフェイルセーフ&ロールバック手順
articleESLint でアーキテクチャ境界を守る:層間 import を規制する設計パターン
articleESLint no-restricted-* 活用レシピ集:API 禁止・依存制限・危険パターン封じ込め
articleESLint × Vitest/Playwright:テスト環境のグローバルと型を正しく設定
articleESLint × TypeScript「Parsing error: Cannot read file 'tsconfig.json'」完全解決ガイド
articleTypeScript 破壊的変更をブロック!CI で型の後方互換性をチェックする仕組み
articleTypeScript SDK 設計の定石:ビルダー × ジェネリクスで直感的かつ安全な API を作る
articleTypeScript タプル/配列操作チートシート:`Length`・`Push`・`Zip`・`Chunk`を型で書く
articleTypeScript Project References 入門:大規模 Monorepo で高速ビルドを実現する設定手順
articleTypeScript Null 安全戦略の比較検証:ts-reset vs strictNullChecks vs noUncheckedIndexedAccess
articleGit 歴史改変の哲学:クリーン履歴 vs 事実履歴を使い分ける判断軸
articleFFmpeg 「moov atom not found」修復術:壊れた MP4 を救う再配置テクニック
articleComfyUI と Automatic1111 を徹底比較:自由度・速度・拡張性の実測レポート
articleESLint × TypeScript「Parsing error: Cannot read file 'tsconfig.json'」完全解決ガイド
articleCodex が誤ったコードを出すときの対処:再現最小化・拘束条件・テスト駆動の適用
articleDify RAG でヒットしないとき:埋め込み品質・分割・検索パラメータの診断術
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来