TypeScript: allowSyntheticDefaultImports doesn't work in TypeScript > 1.8.0

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

"compilerOptions": {
    "target": "es6",
    "module": "system",
    "allowSyntheticDefaultImports": true
}

And the following test code:

import classNames from "classnames";
let classNamesResult = classNames(["allowSyntheticDefaultImports", "is", "here"]);

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:

Uncaught TypeError: classnames_1.default is not a function

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 3
  • Comments: 19 (9 by maintainers)

Most upvoted comments

If I change allowSyntheticDefaultImports: false then the output is the same. Is this expected?

allowSyntheticDefaultImports does not change the output. All what allowSyntheticDefaultImports is tells the compiler that at runtime your loader (e.g. SystemJs) will perform this operation of mapping modules to default imports, and thus avoids the error at build time.

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.

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 module: 0, which means none. It used to be if you didn’t specify a module kind, but were targeting ES6, the emitted module kind would be ES6. That logic still holds, but we also distinguish now between not setting a module kind, and explicitly setting it to none (0 in this case). The above is probably generating an error during compilation (that your code uses modules but the compiler sets modules to none), which may or may not be visible depending on how that tool uses the API, and but falling back to the new emit default of CommonJS modules.

If the above module setting was set to 5 (for ES2015), or probably even if it was removed all together (so it is undefined instead of a number), it will probably behave like it used to.