Module can only be default-imported using esModuleInterop flag

avatar
Borislav Hadzhiev

Last updated: Feb 28, 2024
3 min

banner

# 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 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.

# Set the esModuleInterop option to true

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

tsconfig.json
{ "compilerOptions": { "esModuleInterop": true, "allowSyntheticDefaultImports": true, // ... rest } }
The code for this article is available on GitHub

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'));

now import works as expected

If this doesn't solve the issue, try restarting your IDE and your development 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 and setting esModuleInterop to true fixes these issues.

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

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

The code for this article is available on GitHub

When enabled, allowSyntheticDefaultImports allows us to write our imports without using an asterisk * when the module doesn't 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 doesn't 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 that there is no default object that we can import from the module.

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

# Using the import * as X syntax

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'));
The code for this article is available on GitHub

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'.

I've also written a detailed guide on how to import values from another file in TS.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

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.