Skip to content
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 works differently for dynamic ESM imports of CommonJS modules #22456

Closed
deepsweet opened this issue Mar 10, 2018 · 4 comments

Comments

@deepsweet
Copy link

deepsweet commented Mar 10, 2018

TypeScript Version: 2.7.2

Search Terms: "allowSyntheticDefaultImports dynamic import"

Code

import mkdirp from 'mkdirp'
// function mkdirp(dir: string, cd: ...

const test = async () => {
  const mkdirp_ = await import('mkdirp')
  // const mkdirp_: {
  //   default: typeof mkdirp,
  //   sync(dir: string, ...)
}

mkdirp declaration is exported as export = mkdirp and not export default mkdirp.

Expected behavior:

Imported types are the same.

Actual behavior:

It works as expected in the first case – TS checked that there is no default export and returned exported function directly.

It doesn't work as expected in the second case – TS provided types for the module like it has default export, so it wont allow to call mkdirp_() directly but mkdirp_.default().

I'm using Babel for transpilation, so the question is only about types provided by TypeScript, noEmit is true.

Related Issues:

#17444

@Jessidhia
Copy link

Jessidhia commented Mar 12, 2018

Note that import() works like it does in the second case as of webpack 4, and this is also the case in node 9.6.0 with --experimental-modules.

For your sanity, avoid using import() to import anything that is not ESM. If you must dynamically load a CJS module, make a wrapper ESM that reexports its contents.

@deepsweet
Copy link
Author

Hmmm, my bad, you're right. Just found this in Webpack 4 changelog:

import() always returns a namespace object. CommonJS modules are wrapped into the default export

This probably breaks your code, if you used to import CommonJs with import()

@deepsweet
Copy link
Author

Just to be clear: dynamic ESM import will provide default no matter what's inside of imported module? i.e. it will map module.exports to default in case of CJS?

@Jessidhia
Copy link

Yes; CJS will always map to default, because module.exports is not guaranteed to be an object.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants