Support for import d from "cjs" form CommonJS modules with —esModuleInterop
TypeScript 2.7 updates CommonJS/AMD/UMD module emit to synthesize namespace records based on the presence of an __esModule
indicator under —esModuleInterop
.The change brings the generated output from TypeScript closer to that generated by Babel.
Previously CommonJS/AMD/UMD modules were treated in the same way as ES6 modules, resulting in a couple of problems. Namely:
TypeScript treats a namespace import (i.e.
import * as foo from "foo"
) for a CommonJS/AMD/UMD module 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 class or a function.ECMAScript spec stipulates that a namespace record is a plain object, and that a namespace import (foo
in the example above) is not callable, though allowed by TypeScriptSimilarly a default import (i.e.
import d from "foo"
) for a CommonJS/AMD/UMD module as equivalent toconst d = require("foo").default
.Most of the CommonJS/AMD/UMD modules available today do not have adefault
export, making this import pattern practically unusable to import non-ES modules (i.e. CommonJS/AMD/UMD). For instanceimport fs from "fs"
orimport express from "express"
are not allowed.
Under the new —esModuleInterop
these two issues should be addressed:
- A namespace import (i.e.
import * as foo from "foo"
) is now correctly flagged as uncallabale. Calling it will result in an error. - Default imports to CommonJS/AMD/UMD are now allowed (e.g.
import fs from "fs"
), and should work as expected.
Note: The new behavior is added under a flag to avoid unwarranted breaks to existing code bases. We highly recommend applying it both to new and existing projects.For existing projects, namespace imports (
import * as express from "express"; express();
) will need to be converted to default imports (import express from "express"; express();
).
Example
With —esModuleInterop
two new helpers are generated importStar
and importDefault
for import *
and import default
respectively.For instance input like:
import * as foo from "foo";
import b from "bar";
Will generate:
"use strict";
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;
}
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
}
exports.__esModule = true;
var foo = __importStar(require("foo"));
var bar_1 = __importDefault(require("bar"));