Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

TypeScript · Const

esModuleInterop

Enables more accurate interoperability between ES-style imports and CommonJS, AMD, or UMD modules. It changes checking and emitted helpers so default imports work as expected and namespace imports remain valid module objects.

Since
2.7

How it works

esModuleInterop changes both checking and CommonJS-oriented emit so default imports work with CommonJS, AMD, and UMD modules, while namespace imports follow the ES module rule that their value must be an object. Enabling it also turns on allowSyntheticDefaultImports for type compatibility.

Syntax

{
  "compilerOptions": {
    "esModuleInterop": true
  }
}

Parameters

NameTypeDescription
esModuleInteropbooleanBoolean compiler option; when true, adjusts module checking and emitted JavaScript for CommonJS, AMD, and UMD interoperability.

Key points

  • The option was introduced in TypeScript 2.7 to address mismatches between TypeScript’s module analysis and existing transpiler behavior.
  • It corrects both flawed CommonJS assumptions: callable namespace imports and default-import handling.
  • CommonJS-oriented output uses helper functions to provide compatibility for namespace and default interop.
  • The option automatically enables allowSyntheticDefaultImports, improving type compatibility for default imports.
  • Third-party emitters commonly follow this interop model, so enabling the option helps TypeScript’s checking match their output.
  • The documentation recommends enabling the option for applications containing CommonJS code.

Common mistakes

  • Namespace imports do not include inherited properties; use a default import for modules whose API relies on the prototype chain.
  • If minimizing import transformations and helper inclusion is the goal, consider verbatimModuleSyntax rather than turning this option off.

Example: Default-import a CommonJS module

import path from "node:path";

console.log(path.basename("/tmp/report.txt"));

With CommonJS-compatible interop enabled, a default import can consume Node’s CommonJS-style module exports and run after compilation.

When to use it

Migrate CommonJS dependencies

A TypeScript application imports CommonJS packages and emits JavaScript with tsc.

Match third-party emit

A project is type-checked by TypeScript but emitted by a bundler or transpiler with Babel-like interop.

Use default imports consistently

A codebase wants default-import syntax for CommonJS or UMD packages.

Interview questions

QWhat problem does esModuleInterop solve?

It makes TypeScript’s module checking and emitted CommonJS interop agree with the behavior used by established transpilers and bundlers. It also fixes callable namespace imports and supports default-import syntax for CommonJS-style modules.

Follow-up: What happens to allowSyntheticDefaultImports? Enabling esModuleInterop enables it automatically, affecting type compatibility even where emit is handled elsewhere.

QHow does the option change namespace and default imports?

Without the option, TypeScript historically modeled a namespace import like a direct require result and modeled a default import like its .default property. Those assumptions are not generally compatible with CommonJS module shapes.

Follow-up: Why can’t a namespace import be callable under the ES module rules? A namespace import must produce an object-like module namespace, so callable CommonJS exports need a different import form.

QWhen is enabling it especially important?

For applications that use TypeScript to emit JavaScript, enabling or disabling it generally does not change whether error-free code runs, because checking and emit remain aligned in either mode. It matters more when a third-party bundler or transpiler emits the application, because those tools commonly use equivalent interop behavior.

Follow-up: What should a library author consider? verbatimModuleSyntax can make the module form explicit and avoid ambiguity for consumers with different interop settings.

  • allowSyntheticDefaultImports
  • verbatimModuleSyntax
  • import * as
  • default import
  • CommonJS
  • AMD
  • UMD

Source: TypeScript: TSConfig Option: esModuleInterop. Checked 2026-10-15.