I have been unable to find a clear explanation of what to do in this case:
Concretely:
// npm i lodash.frompairs @types/lodash.frompairs
import fromPairs = require('lodash.frompairs')
I am trying to create 2 builds of my library: 1 that exposes a CommonJS export, 1 that exposes an ES2015 export. Concretely:
tsc -m commonjs -t es5 Succeedstsc -m es2015 -t es2015 Fails with error TS1202: Import assignment cannot be used when targeting ECMAScript 2015 modulesDo I need to introduce System/Browserify into my build, or is it possible to get this to work correctly with TSC?
The handbook's advice is:
When importing a module using
export =, TypeScript-specificimport module = require("module")must be used to import the module.
Relevant issues:
My full tsconfig.json:
{
"compilerOptions": {
"allowSyntheticDefaultImports": false,
"declaration": false,
"forceConsistentCasingInFileNames": true,
"jsx": "react",
"lib": [
"dom",
"es2015",
"es2016.array.include"
],
"module": "commonjs",
"moduleResolution": "node",
"noImplicitAny": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"preserveConstEnums": true,
"pretty": true,
"sourceMap": true,
"strictNullChecks": true,
"target": "es6"
},
"files": [
"index.tsx",
"test.tsx"
]
}
lodash.frompairs is a commonjs module, it exports a function as the module object, i.e. equivalent to export = function frompairs(...) in TypeScript.
TypeScript implementation for ES6 modules adheres to the spec, in the sense that import d from "mod" means get the member called "default" on the module object, and add a local name binding for it in this file and call it d. The generated code does that as well.
It is important to note that the ES6 spec does not describe interop with CommonJS modules, as this is outside the scope of what the committee does.
Also as per the ES6 spec, If you want to get the module object then use import * as m from "mod". The ES6 spec also stipulates that a module object can not be callable. so import * as m from "mod";
m(); is an error in ES6 (TypeScript allows you to do that today, but that is a bug that we have not fixed).
Obviously this does not work in the case of CommonJS modules that override the whole module object. our recommendation here is to use the pre-ES6 import ... = require(..) syntax as that matches the CommonJS/AMD semantics accurately. The down side, is that you can not target ES6 as a module output.
When TS implemented supported for ES6 modules, CommonJS interop story was not clear. i think we now have better understanding of what NodeJS will be doing moving forward and we should be able to allow importing CommonJS modules as default imports using import d from "mod" ES6 import form.
To calrify my erlier commment, Today an import of the form:
import d from "foo";
console.log(d);
today emits to:
var foo = require("foo");
console.log(foo.default);
under the earlier proposal it would emit instead:
var foo = require("foo"), foo_1 = foo && foo.__esModule ? foo : { default: foo };
console.log(foo_1.default);
@mhegazy Thank you for the explanation - it's very helpful.
we should be able to allow importing CommonJS modules as
defaultimports usingimport d from "mod"ES6 import form.
var foo = require("foo"), foo_1 = foo && foo.__esModule ? foo : { default: foo }; console.log(foo_1.default);
If I understand right, are you saying that you guys are planning to change emitted output for imported CommonJS modules to the above? If yes, is there an issue tracking it that I can follow?
@DanielRosenwasser is working on one. we will be discussing it in the language design meeting this Friday. so stay tuned
google closure also doesn't like these "fake" commonJS modules :p it never reads the default property.
Any progress with interoperating with CommonJS modules?
Any progress with importing CommonJS modules as es6 imports?
Currently I am using:
import difference = require("lodash/difference");
https://github.com/Microsoft/TypeScript/issues/16093 tracks this work.
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.