DEV Community

tmhao2005
tmhao2005

Posted on

Understand "esModuleInterop" option in Typescript

Here are couple of cases that I have tested how the option esModuleInterop of Typescript compiler (tsc) works.

Each test will have 2 different imports (one is default import and an namespace import) and we'll check the generated code.

#1

  • { esModuleInterop: false } with tsc
import * as foo from "foo"; import bar from "bar"; console.log(foo, bar) // JS "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var foo = require("foo"); var bar = require("bar"); // I'm not sure why (`.default`), but most of `commonjs` modules  // won't export this value which causes void 0 console.log(foo, bar.default); 
Enter fullscreen mode Exit fullscreen mode

#2

  • { esModuleInterop: true } with tsc:
import * as foo from "foo"; import bar from "bar"; console.log(foo, bar) // 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 (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var foo = __importStar(require("foo")); var bar = __importDefault(require("bar")); // In this case, `foo` won't work if `foo` is `commonjs` which is a single export:  // `module.exports = {}`  // then it would return { default: {} } console.log(foo, bar.default); 
Enter fullscreen mode Exit fullscreen mode

Finally, we have an issue with webpack:

Let's say to have module foo which is quite common pattern:

- lib -- index.cjs.js -- index.esm.js 
Enter fullscreen mode Exit fullscreen mode

index.cjs.js

module.exports = {} 
Enter fullscreen mode Exit fullscreen mode

index.esm.js

export default {} 
Enter fullscreen mode Exit fullscreen mode

Then import:

import * as foo from "foo" console.log(foo) 
Enter fullscreen mode Exit fullscreen mode

with foo's package.json:

{ main: './lib/index.cjs.js', module: './lib/index.esm.js' } 
Enter fullscreen mode Exit fullscreen mode

would result in in webpack:

var foo = __webpack_require__("./node_modules/foo/lib/index.esm.js"); console.log(foo) // { default: {...} } // But with `cjs`, it works var foo = __webpack_require__("./node_modules/foo/lib/index.cjs.js"); console.log(foo) // {...} 
Enter fullscreen mode Exit fullscreen mode

If webpack takes es2015+ module, it will transform to harmony module.

/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react"); /* harmony default export */ __webpack_exports__["default"] = (Bar); 
Enter fullscreen mode Exit fullscreen mode
  • __webpack_require__ with esm:
// foo.js export default 1; // result __webpack_require__('foo.js'); // { default: 1 } 
Enter fullscreen mode Exit fullscreen mode
  • __webpack_require__ with cjs:
// foo.js module.exports = 1; // result __webpack_require__('foo.js'); // 1 
Enter fullscreen mode Exit fullscreen mode
  • esModuleInterop option won't affect to es2015+ module.

Top comments (0)