MeWrite Docs

This module can only be referenced with ECMAScript imports/exports

TypeScriptでCommonJSとESModulesの相互運用設定が必要な場合のエラー

概要

TypeScriptでCommonJSモジュールをESModules形式(import/export)でインポートする際に、esModuleInteropallowSyntheticDefaultImportsの設定が必要な場合に発生するエラーです。

エラーメッセージ

This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.

Module 'xxx' has no default export.

Cannot find module 'xxx' or its corresponding type declarations.

原因

  1. esModuleInterop未設定: CommonJSモジュールをESM形式でインポート
  2. デフォルトエクスポートなし: module.exportsをデフォルトインポートで取得
  3. 型定義の不一致: @typesパッケージとモジュール本体の不整合
  4. Node.jsモジュール解決: ESMとCJSの混在

解決策

1. tsconfig.jsonで設定

1
2
3
4
5
6
{
  "compilerOptions": {
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true
  }
}

2. インポート形式を修正

1
2
3
4
5
6
7
// esModuleInterop: false の場合
import * as express from 'express';
import * as React from 'react';

// esModuleInterop: true の場合(推奨)
import express from 'express';
import React from 'react';

3. CommonJSスタイルのインポート

1
2
3
4
5
// require形式(TypeScriptでも使用可能)
const express = require('express');

// または import = require 形式
import express = require('express');

4. 名前付きエクスポートを使用

1
2
3
4
5
// module.exports = { foo, bar } の場合
import { foo, bar } from 'some-cjs-module';

// デフォルトエクスポートと名前付きの両方
import module, { namedExport } from 'some-module';

5. Node.js ESMモードの設定

1
2
3
4
// package.json
{
  "type": "module"
}
1
2
3
4
5
6
7
8
// tsconfig.json
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "NodeNext",
    "esModuleInterop": true
  }
}

6. 型定義のインストール

1
2
3
4
5
# 型定義をインストール
npm install -D @types/express
npm install -D @types/node

# 型定義がない場合は宣言ファイルを作成
1
2
3
4
5
// types/untyped-module.d.ts
declare module 'untyped-module' {
  const content: any;
  export default content;
}

7. 動的インポート

1
2
3
4
5
// 動的インポートでCJSモジュールを読み込む
async function loadModule() {
  const module = await import('some-cjs-module');
  const defaultExport = module.default;
}

8. Babelとの連携

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-typescript', {
      allowDeclareFields: true
    }]
  ],
  plugins: [
    '@babel/plugin-transform-modules-commonjs'
  ]
};

esModuleInteropの動作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// CommonJSモジュール (cjs-module.js)
// module.exports = function() { ... }

// esModuleInterop: false
import * as cjsModule from 'cjs-module';
cjsModule(); // Error: cjsModule is not a function
cjsModule.default(); // これも動かない場合がある

// esModuleInterop: true
import cjsModule from 'cjs-module';
cjsModule(); // OK: デフォルトエクスポートとして扱われる

推奨設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// tsconfig.json(モダンなプロジェクト向け)
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

よくある間違い

  • import * asimport defaultを混同する
  • @typesパッケージのバージョンが古い
  • Node.jsとブラウザで異なるモジュール解決を使う

関連エラー

参考リンク

TypeScript の他のエラー

最終更新: 2025-12-13