Skip to content

Node.jsでTypeScriptファイルの拡張子「.ts」が認識されない問題

Herokuなどの環境でTypeScriptアプリケーションを実行する際に、Unknown file extension ".ts"というエラーが発生することがあります。この問題は、Node.jsのESモジュール(ESM)とCommonJSの設定が適切に構成されていない場合に起こります。

問題の原因

このエラーの主な原因は以下の組み合わせです:

  • package.json"type": "module"が設定されている
  • tsconfig.jsonでESモジュール関連の設定がされている
  • ts-nodeがESモジュールモードで実行されていない
json
{
  "type": "module",  // ← これが原因の一つ
  "scripts": {
    "start": "ts-node src/App.ts"  // ← ESM対応が必要
  }
}

解決方法

方法1: CommonJSを使用する(推奨)

最もシンプルな解決策は、CommonJSモードを使用することです。

  1. package.jsonから"type": "module"を削除
  2. tsconfig.jsonをCommonJS用に設定
json
{
  "compilerOptions": {
    "target": "ES6",
    "module": "CommonJS",  // ← CommonJSを使用
    "moduleResolution": "node",
    "esModuleInterop": true,
    "outDir": "dist"
  }
}

TIP

CommonJSモードでは、従来のrequire構文とimport構文の両方が使用できます。esModuleInterop: trueによって互換性が確保されます。

方法2: ESモジュールを維持する場合

ESモジュールを使用する必要がある場合は、以下の設定が必要です。

json
{
  "type": "module",
  "scripts": {
    "start": "ts-node --esm src/App.ts"  // ← --esmフラグを追加
  }
}
json
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "node"
  },
  "ts-node": {
    "esm": true  // ← ts-nodeにESMを有効化
  }
}

実行時には以下のいずれかの方法を使用します:

bash
# 方法1: --esmフラグを使用
ts-node --esm src/App.ts

# 方法2: Node.jsのloaderを使用
node --loader ts-node/esm src/App.ts

方法3: モダンな代替ツールを使用する

最近ではts-nodeの代わりにより優れたツールが利用できます。

tsxの使用(2024年現在、推奨)

bash
npm install -D tsx
json
{
  "scripts": {
    "dev": "tsx watch src/App.ts",
    "start": "tsx src/App.ts"
  }
}

vite-nodeの使用

bash
npm install -D vite-node
json
{
  "scripts": {
    "dev": "vite-node --watch src/App.ts"
  }
}

INFO

tsxとvite-nodeは、ESモジュールをネイティブにサポートし、設定が少なくて済むという利点があります。

Herokuへのデプロイ設定

Herokuでは、ビルドプロセスを適切に設定する必要があります。

json
{
  "scripts": {
    "build": "tsc",
    "start": "node dist/App.js"
  },
  "engines": {
    "node": ">=18.0.0"
  }
}

WARNING

本番環境では、TypeScriptをJavaScriptにコンパイルしてから実行することを推奨します。これにより、パフォーマンスが向上し、実行時コンパイルのオーバーヘッドを避けられます。

よくある問題と解決策

Node.jsのバージョン問題

特定のNode.jsバージョン(特にv18)ではESモジュール関連の問題が発生することがあります。

bash
# Node.jsのバージョンを確認
node --version

# 必要に応じてバージョン変更(nvmを使用)
nvm install 20
nvm use 20

拡張子の明示的な指定

ESモジュールでは、インポート時に拡張子を明示する必要がある場合があります。

typescript
// 従来
import { MyModule } from './my-module'

// ESMでは拡張子が必要な場合がある
import { MyModule } from './my-module.js'

まとめ

シナリオ推�解決策
新しいプロジェクトtsxまたはvite-nodeを使用
既存プロジェクト(CommonJS)module: "CommonJS"設定
既存プロジェクト(ESM維持)ts-node --esmと設定
本番環境TypeScriptを事前コンパイル

TypeScriptとNode.jsのモジュールシステムは歴史的に複雑な経緯がありますが、適切な設定とモダンなツールを使用することで、これらの問題は解決できます。

最新の情報については、TypeStrong/ts-nodeのGitHubリポジトリを確認することをお勧めします。