tsconfig

esModuleInterop

understanding esModuleInterop

CJS module을 ES6 모듈로 import 할 때 문제 발생한다. CJS는 (* as something)으로 import 해야한다.

// node_modules/moment/index.js
exports = moment;

ssssss

// index.ts file in our app
import * as moment from 'moment';
moment(); // not compliant with es6 module spec

// transpiled js (simplified):
const moment = require('moment');
moment();

*exports 변수와 어느정도 동일하다. 하지만 es6 module spec을 준수하지 않는다. 스펙에서, star import의 namespace record는 moment()와 같이 호출되는 것이 아닌 plain object만 될 수 있다.

Solution

esModuleInterop 플래그로 CJS 모듈을 es6 모듈로 import할 수 있다.

// index.ts file in our app
import moment from 'moment';
moment(); // compliant with es6 module spec

// transpiled js with esModuleInterop (simplified):
const moment = __importDefault(require('moment'));
moment.default();

유효한 es6 module spec이 되고 잘 동작한다. moment는 star import의 namespace가 아니기 때문이다. 걍 default import다.

하지만 어케 동작할까? default import를 했기 때문에, moment 객체의 default property를 호출한다. 하지만 exports object에서 default property를 선언한 적이 없다. __importDefault 함수에서 CJS module에게 default property에 exports를 할당한다.

var __importDefault =
  (this && this.__importDefault) ||
  function(mod) {
    return mod && mod.__esModule ? mod : { default: mod };
  };

As You can see, we import es6 modules as it is, but CommonJS modules are wrapped into object with default key. This makes possible to import defaults on CommonJS modules.

__importStar does the similar job - it returns untouched esModules, but translate CommonJS modules into modules with default property:

Last updated

Was this helpful?