-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allowSyntheticDefaultImports doesn't work in TypeScript > 1.8.0 #7518
Comments
Can you show the difference in compiled code (i.e. what is emitted differently) between the two versions you think is the error. TypeScript has no runtime support for synthetic defaults, it simply allows for the fact they may be present at runtime. It is the module loader (SystemJS in this case) that creates the synthetic default. From the above it looks like your loader is not creating the |
Here's the diff between the output: --- /home/kenjiru/typescript-1.8.0-output.js
+++ /home/kenjiru/typescript-1.8.7-output.js
@@ -46,13 +46,8 @@
"use strict";
- var _classnames = __webpack_require__(1);
-
- var _classnames2 = _interopRequireDefault(_classnames);
-
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-
- var classNamesResult = (0, _classnames2.default)(["allowSyntheticDefaultImports", "is", "here"]);
+ var classnames_1 = __webpack_require__(1);
+ var classNamesResult = classnames_1.default(["allowSyntheticDefaultImports", "is", "here"]);
console.log(classNamesResult);
/***/ }, I've put up a small project showcasing the problem. I'm building this using webpack-1.12.14 and tsloader-0.7.2, but this should be irrelevant. |
The output is coming from Babel, sorry I missed this detail. I'm trying to figure out why it's different when changing the compiler. I assume that both tsc and babel will return the same output for the same input. So a possible culprit here might be the tsloader. |
Yeah, sorry, but doesn't appear to be us. (From the output, I'm guessing you have WebPack in the mix adding code in your build pipeline also). |
Looking at the source code of ts-loader, I've noticed that it's using the Compiler API to transpile the ts files. So it's doing something like this: var ts = require("typescript");
var content =
"import classNames from 'classnames';" +
"let classNamesResult = classNames(['allowSyntheticDefaultImports', 'is', 'here']);" +
"console.log(classNamesResult);";
var compilerOptions = {
module: 0,
jsx: 1,
target: 2,
noImplicitAny: false,
removeComments: false,
preserveConstEnums: true,
sourceMap: true,
allowSyntheticDefaultImports: true
};
var result = ts.transpileModule(content, {compilerOptions: compilerOptions});
console.log(result.outputText); Now the problem is that with TypeScript 1.8.0 we get this results import classNames from 'classnames';
let classNamesResult = classNames(['allowSyntheticDefaultImports', 'is', 'here']);
console.log(classNamesResult);
//# sourceMappingURL=module.jsx.map While with TypeScript 1.8.7 it shows this: "use strict";
const classnames_1 = require('classnames');
let classNamesResult = classnames_1.default(['allowSyntheticDefaultImports', 'is', 'here']);
console.log(classNamesResult);
//# sourceMappingURL=module.jsx.map |
Running tsc from the command line also return different results.
src/App.ts import classNames from "classnames";
let classNamesResult = classNames(["allowSyntheticDefaultImports", "is", "here"]);
console.log(classNamesResult); tsconfig.json {
"compileOnSave": false,
"filesGlob": [
"../typings/**/*.*.ts",
"**/*.{ts}"
],
"compilerOptions": {
"jsx": "preserve",
"target": "es6",
"noImplicitAny": false,
"removeComments": false,
"preserveConstEnums": true,
"sourceMap": true,
"module": "system",
"allowSyntheticDefaultImports": true
},
"files": [
"../typings/browser.d.ts",
"App.ts"
]
} It return the following for TypeScript 1.8.0: System.register("App", ["classnames"], function(exports_1) {
"use strict";
var classnames_1;
var classNamesResult;
return {
setters:[
function (classnames_1_1) {
classnames_1 = classnames_1_1;
}],
execute: function() {
classNamesResult = classnames_1.default(["allowSyntheticDefaultImports", "is", "here"]);
console.log(classNamesResult);
}
}
});
//# sourceMappingURL=typescript-1.8.0.js.map And the following for TypeScript 1.8.7: System.register("App", ["classnames"], function(exports_1, context_1) {
"use strict";
var __moduleName = context_1 && context_1.id;
var classnames_1;
var classNamesResult;
return {
setters:[
function (classnames_1_1) {
classnames_1 = classnames_1_1;
}],
execute: function() {
classNamesResult = classnames_1.default(["allowSyntheticDefaultImports", "is", "here"]);
console.log(classNamesResult);
}
}
});
//# sourceMappingURL=typescript-1.8.7.js.map |
Is there an issue with the above? The emit looks semantically identical to me. |
For future references the |
The problem is with the Compiler API results, they are quite different. The TypeScript 1.8.0 result Babel will transpile the code to (which works fine in the browser): 'use strict';
var _classnames = __webpack_require__(1);
var _classnames2 = _interopRequireDefault(_classnames);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var classNamesResult = (0, _classnames2.default)(['allowSyntheticDefaultImports', 'is', 'here']);
console.log(classNamesResult);
//# sourceMappingURL=module.jsx.map And for the TypeScript 1.8.7 will transpile to: "use strict";
var classnames_1 = __webpack_require__(1);
var classNamesResult = classnames_1.default(['allowSyntheticDefaultImports', 'is', 'here']);
console.log(classNamesResult);
//# sourceMappingURL=module.jsx.map Which will throw the following error in the browser:
|
Looking at your compiler output, the results are not semantically different. However, backing up to the API sample, the issue likely is the setting: var compilerOptions = {
module: 0,
jsx: 1,
target: 2,
noImplicitAny: false,
removeComments: false,
preserveConstEnums: true,
sourceMap: true,
allowSyntheticDefaultImports: true
}; The above is specifying If the above |
You are right, this issue is a result of the compiler becoming more strict about the module target and the ts-loader reading the incorrect value from the configuration file. This seems to be fixed in the latest version of ts-loader 0.8.1, which was released a few days ago. Thank you very much for taking the time to look into this issue and for the detailed explanation. |
Is a regression added recently on this issue? Here is my configuration:
and here is the code generated:
for the import:
The same issue I have on the react import. Thanks in advance for the any help! |
@gitsupersmecher |
Thanks for the reply. What I am saying is that it does not matter if allowSyntheticDefaultImports is set or not. The output of the tsc -p is wrong. I should not have ".default" in "classnames_1.default". |
You wrote a default import and got a default import. What's incorrect about that? |
If I change allowSyntheticDefaultImports: false then the output is the same. Is this expected? |
|
Thank you, @mhegazy. Appreciate your answer. I did not know that, and your answer clarified it. And thank you @RyanCavanaugh and @aluanhaddad for your input. |
It seems that the allowSyntheticDefaultImports option doesn't work with the latest version of the TypeScript compiler. It works as expected with TypeScript 1.8.0.
TypeScript Version:
1.8.3 / 1.8.7
Code
I have the following configuration in tsconfig.json
And the following test code:
Expected behavior:
classNamesResult == "allowSyntheticDefaultImports is here"
Actual behavior:
The code compiles fine, but it fails at runtime, with the following error in the browser console:
The text was updated successfully, but these errors were encountered: