How To Solve “Module can only be default-imported using esModuleInterop flag” in TypeScript

Modules are a way to organize your code into small, manageable chunks and allow programs to combine code from different parts of your application. Sometimes during development, we get an error “Module can only be default-imported using esModuleInterop flag“, the reason is we import the CommonJS module into the ES6 module codebase, to solve this error we turn on esModuleInterop.

The cause of the error “Module can only be default-imported using esModuleInterop flag”

By default (esModuleInterop is false or unset), TypeScript supports CommonJS/AMD/UMD modules just like ES6 modules. In doing so, there are two aspects, in particular, that cause misunderstanding:

Do the same as importing namespaces, e.g. import * as moment from "moment" acts the same as const moment = require("moment")

Or import module from "module" acts the same as const module = require("module").default

This difference creates two problems:
The ES6 module spec says that a namespace import (import * as x) can only be an object, just like TypeScript treats = require("x") then TypeScript calls that import as a function. With say not working as expected.
While ES6 modules are valid, most CommonJS/AMD/UMD modules and libraries are not as closely compatible as the TypeScript implementation.

Error Example:

import * as module from "module";

// Not compatible with ES6 module
module();

Output:

Module can only be default-imported using esModuleInterop flag

We see that * is equivalent to an output variable. It works fine but not as described in ES6. When importing a module, the namespace entry (module in our case) is simply not declared (module() is not allowed).

Error Example:

const module = require("module");

// Not compatible with ES6 module
module();

Output:

Module can only be default-imported using esModuleInterop flag

So, what are the solutions?

To solve this error you need to enable esModuleInterop, this will solve the problems in your TypeScript code. You need to add this line to the file tsconfig.json

{
  "compilerOptions": {
  	"esModuleInterop": true,
  	"allowSyntheticDefaultImports": true,
  }
}

After enabling esModuleInterop, we modify the code as follows

Example:

import module from 'module'

// Now the module is working
module();
const module = __importDefault(require('module'));

// Now the module is working
module.default();

Now module is not the namespace of import *, so it can work with the ES6 module. Enabling esModuleInterop will also enable allowSyntheticDefaultImports. It allows default import from modules without default export. It doesn’t affect code generation. Just checking.

Summary

So through the article, we have solved the error “Module can only be default-imported using esModuleInterop flag” by enabling esModuleInterop mode. Hope the article is useful to you, Thanks for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *