Module can only be default-imported using esModuleInterop flag

avatar

Borislav Hadzhiev

Last updated: Mar 19, 2022

banner

Photo from Unsplash

Module can only be default-imported using esModuleInterop flag #

The error "Module can only be default-imported using esModuleInterop flag" occurs when we try to import a CommonJS module into an ES6 module. To solve the error, set the esModuleInterop option to true in your tsconfig.json file.

module can only be default imported

Here is an example of how the error occurs.

index.ts
// ⛔️ Error: Module '"path"' can only be // default-imported using the 'esModuleInterop' flag ts(1259) // This module is declared with using 'export =', and // can only be used with a default import when // using the 'esModuleInterop' flag. import path from 'path'; console.log(path.join(__dirname, './another-file.ts')); export const num = 42;

The issue here is that path is a CommonJS module that uses the exports and require syntax and we are trying to import it into an ES6 module using a default import.

To solve the error, set the esModuleInterop option to true in your tsconfig.json file.

tsconfig.json
{ "compilerOptions": { "esModuleInterop": true, "allowSyntheticDefaultImports": true, // ... rest } }

Now our import works as intended:

index.ts
import path from 'path'; export const num = 42; // ✅ "/home/borislav/Desktop/typescript/src/another-file.ts" console.log(path.join(__dirname, './another-file.ts'));
If this doesn't solve the issue for you, try restarting your IDE and your server.

The esModuleInterop option is set to false by default, which causes it to treat CommonJS modules similar to ES6 modules. This causes some issues. Setting esModuleInterop to true fixes these issues.

The esModuleInterop setting changes the behavior of the compiler with two helper functions, which provide a shim to make the emitted JavaScript compatible.

When you set esModuleInterop to true, you are also enabling the allowSyntheticDefaultImports option.

When enabled, allowSyntheticDefaultImports allows us to write our imports without using an asterisk * when the module does not explicitly specify a default export.

index.ts
import React from 'react'; import path from 'path'; import fs from 'fs';

Instead of:

index.ts
import * as React from 'react'; import * as path from 'path'; import * as fs from 'fs';

For example, the path module does not provide a default export, so if we try to import it with allowSyntheticDefaultImports set to false, we would get the error.

index.ts
// ⛔️ Error: Module '"path"' can only be // default-imported using the 'esModuleInterop' flag ts(1259) import path from 'path';

The cause of the error is - there is no default object which we can import from the module.

If this doesn't solve the issue for you, try restarting your IDE and your server.

An alternative approach is to use the import * as x syntax.

index.ts
import * as path from 'path'; export const num = 42; // ✅ "/home/borislav/Desktop/typescript/src/another-file.ts" console.log(path.join(__dirname, './another-file.ts'));

Note that imports such as import * as x only account for properties that are owned (not inherited via the prototype chain).

If importing a module that uses inherited properties, you have to use the default import syntax - import path from 'path'.

Conclusion #

The error "Module can only be default-imported using esModuleInterop flag" occurs when we try to import a CommonJS module into an ES6 module. To solve the error, set the esModuleInterop option to true in your tsconfig.json file.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.