This is the restated #27293. CC @ryanelian
TypeScript Version: master (471bc64)
Search Terms: esModuleInterop allowSyntheticDefaultImports error undefined default import export
Code: In the b subdirectory, compile with tsc -b . and run with node index.js.
// tsconfig.common.json
{
"compilerOptions": {
"composite": true,
"declaration": true,
"target": "es6",
"module": "commonjs",
"esModuleInterop": true
}
}
// a/tsconfig.json
{
"extends": "../tsconfig.common.json",
"files": [
"index.ts"
]
}
// a/index.ts
export const foo = 42;
// b/tsconfig.json
{
"extends": "../tsconfig.common.json",
"references": [
{ "path": "../a" }
],
"files": [
"index.ts"
]
}
// b/index.ts
// Actual: compile OK. Expected: compile error.
import A from "../a";
// Actual: runtime error.
console.log(A.foo);
Expected behavior: The generated a/index.d.ts uses some new syntax to mark the module as an ES6 module, so allowSyntheticDefaultImports does not apply to it and the default import in b/index.ts is a compile error.
Actual behavior: allowSyntheticDefaultImports applies to module a, so at compile time, the default import is accepted and resolves to the entire module, but at runtime, A.foo raises an error:
REDACTED/b/index.js:7
console.log(a_1.default.foo);
^
TypeError: Cannot read property 'foo' of undefined
Playground Link: N/A, multiple files
Related Issues: #27293
Please note: The marker actually already exists, we just don't emit it. If the declaration file has export const __esModule: true, then we're guaranteed to treat it like a module and not create a synthetic namespace in the typesystem.
I am running into this issue as well
I'm running into the same issue. I think one way to fix this is to update the __importDefault tslib helper to be a bit more lenient? I'm not 100% sure if this is the behaviour we want though.
I.e., update https://github.com/Microsoft/tslib/blob/ca03390c0bcf14ae0ef8090dec52de5059ed2e96/tslib.js#L220-L222 from
return (mod && mod.__esModule) ? mod : { "default": mod };
to
return (mod && mod.__esModule && mod.hasOwnProperty("default")) ? mod : { "default": mod };
As discussed in https://github.com/Microsoft/tslib/pull/64, the workaround I suggested above is not the right solution to this problem.
For anyone running into this issue: you're doing it wrong.
The error is that you're using import X from 'module' when module does _not_ have a default import. import X does not work like const X = require()
Solution: either use:
import * as X from 'module'
or maybe import it as a CJS module with:
import X = require('module')
The bug is that the compiler should error, _not_ that it doesn't work at runtime.
Most helpful comment
For anyone running into this issue: you're doing it wrong.
The error is that you're using
import X from 'module'whenmoduledoes _not_ have adefaultimport.import Xdoes not work likeconst X = require()Solution: either use:
or maybe import it as a CJS module with:
The bug is that the compiler should error, _not_ that it doesn't work at runtime.