'Understanding esModuleInterop in tsconfig file
I was checking out someone .tsconfig file and there I spotted --esModuleInterop
This is his .tsconfig file
{
"compilerOptions": {
"moduleResolution": "node",
"target": "es6",
"module": "commonjs",
"lib": ["esnext"],
"strict": true,
"sourceMap": true,
"declaration": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"declarationDir": "./dist",
"outDir": "./dist",
"typeRoots": ["node_modules/@types"]
},
"include": ["src/**/*.ts"],
"exclude": ["node_modues"]
}
Here, My primary question is what is "esModuleInterop": true, and
"allowSyntheticDefaultImports": true,. I know they are sort of dependent on the "module": "commonjs", . Can someone try to explain it in the best human language possible?
The official docs for allowSyntheticDefaultImports states
Allow default imports from modules with no default export. This does not affect code emit, just typechecking.
What does that mean? If there isn't any export default then I think the only use case of the import default would be to initialize something? Like a singleton?
The following question/answer does not make sense as well Is there a way to use --esModuleInterop in tsconfig as opposed to it being a flag?
And --esModuleInterop definition on the compiler page
Emit __importStar and __importDefault helpers for runtime babel ecosystem compatibility and enable --allowSyntheticDefaultImports for typesystem compatibility.
Also seemed difficult for me to understand/comprehend
Solution 1:[1]
esModuleInterop generates the helpers outlined in the docs. Looking at the generated code, we can see exactly what these do:
//ts
import React from 'react'
//js
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = __importDefault(require("react"));
__importDefault: If the module is not an es module then what is returned by require becomes the default. This means that if you use default import on a commonjs module, the whole module is actually the default.
__importStar is best described in this PR:
TypeScript treats a namespace import (i.e.
import * as foo from "foo") as equivalent toconst foo = require("foo"). Things are simple here, but they don't work out if the primary object being imported is a primitive or a value with call/construct signatures. ECMAScript basically says a namespace record is a plain object.Babel first requires in the module, and checks for a property named
__esModule. If__esModuleis set totrue, then the behavior is the same as that of TypeScript, but otherwise, it synthesizes a namespace record where:
- All properties are plucked off of the require'd module and made available as named imports.
- The originally require'd module is made available as a default import.
So we get this:
// ts
import * as React from 'react'
// emitted js
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
var React = __importStar(require("react"));
allowSyntheticDefaultImports is the companion to all of this, setting this to false will not change the emitted helpers (both of them will still look the same). But it will raise a typescript error if you are using default import for a commonjs module. So this import React from 'react' will raise the error Module '".../node_modules/@types/react/index"' has no default export. if allowSyntheticDefaultImports is false.
Solution 2:[2]
A small addition to the existing answers - I had this issue when working on tests.
In order to fix it, I had to add the test folder to the imports inside tsconfig:
{
...
"include": [
"src/**/*.ts",
"test/**/*.ts"
],
...
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Titian Cernicova-Dragomir |
| Solution 2 | Volodymyr Bobyr |
