TypeScript『cannot find module』エラーの原因と解決方法を完全ガイド

TypeScript

TypeScript『cannot find module』エラーの原因と解決方法を完全ガイド

TypeScriptでプログラミングをしていると、「cannot find module」というエラーに遭遇することがあります。このエラーは初心者にとって非常に悩ましく、原因の特定も難しいことが多いです。本記事では、このエラーが発生する原因から解決方法まで、初心者でもわかりやすく解説していきます。

「cannot find module」エラーとは

cannot find module」は、TypeScriptがインポート(読み込み)しようとしたモジュールやファイルを見つけられない時に発生するエラーです。エラーメッセージは次のような形で表示されます:

Cannot find module './utils' or its corresponding type declarations.

このエラーが発生すると、プログラムはコンパイルできず、開発が進められなくなります。

エラーが発生する主な原因

1. ファイルパスの指定が間違っている

最も一般的な原因は、インポート時のファイルパスが正確でないことです。以下のような場合が考えられます:

  • ファイル名のスペルが違う
  • 大文字と小文字が一致していない
  • ファイルの実際の場所と異なるパスを指定している
  • ファイルの拡張子を含めている(JavaScriptでは通常、拡張子は省略)

2. tsconfig.jsonの設定が正しくない

tsconfig.jsonはTypeScript コンパイラの設定ファイルです。この設定が不完全だと、モジュール解決がうまく機能しません。特に以下の設定が重要です:

  • moduleResolution:モジュール解決の方式
  • baseUrl:相対パスの基準ディレクトリ
  • paths:パスのエイリアス設定

3. node_modulesが存在しない、または依存関係がインストールされていない

NPMやYarnでインストールした外部パッケージをインポートしようとしても、node_modulesフォルダが存在しないか、パッケージがインストールされていないと、このエラーが発生します。

4. ファイルが実際に存在しない

参照しているファイルやフォルダが、プロジェクトに実際に存在しないケースもあります。

問題解決の手順

ステップ1:ファイルパスを確認する

まず基本に立ち戻って、以下を確認してください:

  1. インポートステートメント内のパス表記が正確か
  2. ファイル名のスペルが完全に一致しているか
  3. 大文字と小文字が区別されているか(特にLinuxやmacOS)
  4. 実際のファイル構造がインポートパスと一致しているか

ファイル構造の例:

project/
  ├── src/
  │   ├── main.ts
  │   ├── utils/
  │   │   └── helper.ts
  │   └── components/
  │       └── Button.ts
  ├── tsconfig.json
  └── package.json

ステップ2:拡張子を確認する

TypeScriptのインポートでは、通常以下のルールに従います:

  • 相対パスの場合:拡張子は通常、省略します
  • 外部パッケージの場合:拡張子を付けない

ステップ3:tsconfig.jsonを確認・修正する

tsconfig.jsonの設定を見直すことが重要です。以下は推奨される基本設定です:

{
  \"compilerOptions\": {
    \"target\": \"ES2020\",
    \"module\": \"commonjs\",
    \"lib\": [\"ES2020\"],
    \"outDir\": \"./dist\",
    \"rootDir\": \"./src\",
    \"strict\": true,
    \"esModuleInterop\": true,
    \"skipLibCheck\": true,
    \"forceConsistentCasingInFileNames\": true,
    \"moduleResolution\": \"node\",
    \"baseUrl\": \"./src\",
    \"paths\": {
      \"@/*\": [\"./*\"]
    }
  },
  \"include\": [\"src\"],
  \"exclude\": [\"node_modules\"]
}

moduleResolutionを「node」に設定すると、Node.jsのモジュール解決アルゴリズムに従います。これはほとんどのプロジェクトで推奨されます。

ステップ4:node_modulesと依存関係を確認する

以下のコマンドで、必要なパッケージがインストールされているか確認し、必要に応じて再インストールします:

npm install
# または
yarn install

また、パッケージがpackage.jsonに登録されているか確認してください。

ステップ5:ファイルの存在を確認する

エディタのファイルツリーで、参照しているファイルが実際に存在するか確認します。場合によってはファイルを作成する必要があります。

実践的なコード例

例1:相対パスでのインポートが失敗する場合

❌ 誤った例:

// main.ts から utils/helper.ts をインポート
import { helperFunction } from './utils/helper.ts'; // 拡張子は不要
import { helperFunction } from './utils/Helper'; // 大文字が違う

✅ 正しい例:

// main.ts から utils/helper.ts をインポート
import { helperFunction } from './utils/helper';

例2:パスエイリアスを使用する場合

tsconfig.jsonに以下を設定:

{
  \"compilerOptions\": {
    \"baseUrl\": \".\",
    \"paths\": {
      \"@components/*\": [\"src/components/*\"],
      \"@utils/*\": [\"src/utils/*\"],
      \"@types/*\": [\"src/types/*\"]
    }
  }
}

その後、以下のようにインポートできます:

// どのファイルからでも同じパスで参照可能
import Button from '@components/Button';
import { helperFunction } from '@utils/helper';
import { UserType } from '@types/user';

例3:外部パッケージをインポートする場合

// 正しいインポート方法
import axios from 'axios';
import { useState } from 'react';
import * as lodash from 'lodash';

もし「Cannot find module 'axios'」というエラーが出たら、以下を実行:

npm install axios
npm install --save-dev @types/axios  // 型定義がある場合

例4:複雑なプロジェクト構造での対応

プロジェクト構造:

src/
  ├── api/
  │   └── user.ts
  ├── utils/
  │   └── validation.ts
  ├── components/
  │   └── UserForm.ts
  └── main.ts

tsconfig.json設定:

{
  \"compilerOptions\": {
    \"baseUrl\": \"./src\",
    \"paths\": {
      \"@api/*\": [\"api/*\"],
      \"@utils/*\": [\"utils/*\"],
      \"@components/*\": [\"components/*\"]
    },
    \"moduleResolution\": \"node\"
  }
}

各ファイルでのインポート:

// components/UserForm.ts
import { getUserData } from '@api/user';
import { validateEmail } from '@utils/validation';

よくある間違いと対策

間違い1:相対パスで拡張子を含める

❌ 間違い:

import { func } from './utils/helper.ts';

✅ 正しい:

import { func } from './utils/helper';

理由:TypeScriptはコンパイル時に拡張子を自動的に解決するため、拡張子を明示的に指定すると見つからなくなります。

間違い2:大文字小文字を混同する

❌ 間違い:

// ファイル名は Button.ts だが
import Button from './button';

✅ 正しい:

import Button from './Button';

理由:Windowsでは大文字小文字が区別されませんが、LinuxやmacOSでは区別されます。本番環境でエラーを避けるため、正確に一致させることが重要です。

間違い3:相対パスの「../」の数が間違っている

❌ 間違い:

// src/components/Button.ts から src/utils/helper.ts をインポート
import { func } from '../../utils/helper'; // ディレクトリが1つ多い

✅ 正しい:

import { func } from '../utils/helper';

間違い4:npm install を実行していない

新しいプロジェクトをクローンした後や、package.jsonに新しいパッケージを追加した後に、npm installを実行し忘れるケースが非常に多いです。

✅ 対策:

npm install
# または以下で確認
npm list package-name

間થি5:型定義パッケージをインストールしていない

JavaScriptで書かれた外部ライブラリを使用する場合、型定義(@types/)を別途インストールする必要があります。

✅ 対策:

npm install --save-dev @types/jquery
npm install --save-dev @types/node

デバッグのコツ

VSCodeの活用

Visual Studio Codeを使用している場合、以下の機能が役立ちます:

  • 「Go to Definition」(F12):インポート元のファイルに移動
  • 「Peek Definition」(Ctrl+Shift+F10):ファイルを開かずにプレビュー
  • 「Find All References」(Ctrl+Shift+H):参照箇所をすべて表示

コンパイルエラーメッセージをよく読む

エラーメッセージには、TypeScriptがどのパスを探索しようとしたかが記載されていることが多いです。このメッセージから、パスの指定間違いを発見できます。

tsconfig.json の検証

以下のコマンドでtsconfig.jsonの妥当性を確認できます:

npx tsc --noEmit

環境別の設定例

Node.js + Express プロジェクト

{
  \"compilerOptions\": {
    \"target\": \"ES2020\",
    \"module\": \"commonjs\",
    \"lib\": [\"ES2020\"],
    \"outDir\": \"./dist\",
    \"rootDir\": \"./src\",
    \"moduleResolution\": \"node\",
    \"baseUrl\": \"./src\",
    \"strict\": true,
    \"esModuleInterop\": true
  }
}

フロントエンド(React + Webpack)プロジェクト

{
  \"compilerOptions\": {
    \"target\": \"ES2020\",
    \"module\": \"esnext\",
    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],
    \"jsx\": \"react-jsx\",
    \"moduleResolution\": \"node\",
    \"baseUrl\": \"./src\",
    \"paths\": {
      \"@/*\": [\"./*\"]
    },
    \"strict\": true,
    \"esModuleInterop\": true
  }
}

まとめ

cannot find module」エラーは、根本的にはモジュール解決のメカニズムに関する問題です。解決するためには、以下の点を順序立てて確認することが重要です:

  1. ファイルパスの正確性:スペル、大文字小文字、ディレクトリ構造を確認
  2. 拡張子の取り扱い:相対パスの場合は拡張子を省略
  3. tsconfig.jsonの設定:moduleResolutionと基本設定を確認
  4. 依存関係のインストール:npm installやyarn installを実行
  5. ファイルの存在:参照しているファイルが実際に存在するか確認

これらのステップを系統的に実行することで、ほとんどのエラーは解決できます。プロジェクトが大きくなるほど、パスエイリアスの設定が有効になります。初期段階で適切に設定することで、将来のトラブルを防ぐことができます。

エラーが発生した際は、焦らずにエラーメッセージをよく読み、上記の対策を順番に試してみてください。TypeScriptの学習を進める上で、このようなエラーとの付き合い方は非常に重要なスキルとなります。

タイトルとURLをコピーしました