no-esmoduleinterop-with-verbatim
Disallow esModuleInterop: true when verbatimModuleSyntax: true is already
configured, because verbatimModuleSyntax supersedes and conflicts with the
interop shim model.
Targeted pattern scopeโ
The compilerOptions.esModuleInterop and compilerOptions.verbatimModuleSyntax
fields in any tsconfig*.json file.
What this rule reportsโ
This rule reports when both "esModuleInterop": true and
"verbatimModuleSyntax": true appear together in compilerOptions.
Why this rule existsโ
esModuleInterop was introduced to allow writing import React from "react"
instead of import * as React from "react" for CJS modules. It works by
injecting interop helper functions at emit time.
verbatimModuleSyntax takes a stricter approach: every import and export is
emitted exactly as written, with no interop shims. The two options represent
fundamentally different mental models of how modules behave. Using both
together produces undefined behavior for default imports of CJS modules โ
verbatimModuleSyntax wins and the esModuleInterop shims are not inserted,
potentially causing silent runtime failures if the code relied on synthetic
default imports.
Remove esModuleInterop when verbatimModuleSyntax is active, and update
any default imports of CJS modules to namespace-style imports.
โ Incorrectโ
{
"compilerOptions": {
"esModuleInterop": true,
"verbatimModuleSyntax": true
}
}
The esModuleInterop shims will not be inserted because verbatimModuleSyntax
takes precedence, making the option a dead setting that misleads readers.
โ Correctโ
Use verbatimModuleSyntax alone for ESM-first codebases:
{
"compilerOptions": {
"verbatimModuleSyntax": true
}
}
Or use esModuleInterop alone for CJS-interop codebases:
{
"compilerOptions": {
"esModuleInterop": true
}
}
When not to use itโ
This rule should always be enabled. There is no well-defined scenario where both flags should be active simultaneously.
Package documentationโ
Rule catalog ID: R007