just
just copied to clipboard
Just packages don't work with TS when "esModuleInterop": false (default)
I have the following tsconfig.json:
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "es2020",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"paths": {
"src/*": ["src/*"]
}
}
}
Please note that it has "allowSyntheticDefaultImports": true
and no "esModuleInterop"
set, which means that it equals to false by default.
So with this setup, we usually import most of our packages with * as something
, like so import * as cookieParser from 'cookie-parser'
.
However with Just packages, like "just-pick", we can't import it at all, because both ways don't work for us (i.e. with * as
or without it).
Importing a package like so makes the imported package to be undefined
(with no TS type-checking errors):
import pick from 'just-pick'
console.log(pick) // <-- undefined
Importing like so works on the runtime but the TS type-cheker would shows an error
import * as pick from 'just-pick'
pick(obj, []) // <-- This expression is not callable. Type 'typeof import(".../node_modules/just-pick/index")' has no call signatures ts(2349)
// Howeever this way it works
(pick as any)(obj, [])
So we had to add "esModuleInterop": true
to our tsconfig.json to make it work, which isn't that bad option, just feel like it's something that should be reported. We have quite a big project with a lot of packages working well, but installing Just packages didn't work.
PS:
Node version: v14.18.3 NPM version: 7.24.2 Typescript version: ^4.2.3
Hi @ilearnio, sorry for the delay in replying.
I'm not a heavy TS user so I had to do quite a bit of reading up on allowSyntheticDefaultImports
and esModuleInterop
.
I'm still not sure I understand all the use cases, but I am a little surprised it's failing. Can you confirm you are using the *.mjs file from Just? Since that declares an explicit default, I did not think esModuleInterop
would be required. I wonder if the issue is the export {objectPick as default}
syntax.
Possibly fixed by #429?
I can confirm that this is still the case. Using just-union 3.1.1
This issue also applies to ESModules with the following config:
"target": "ES2020",
"lib": ["ES2020"],
"module": "NodeNext",
"moduleResolution": "NodeNext",
I found a description of the problem and a possible solution in the TypeScript repository:
https://github.com/microsoft/TypeScript/issues/50067#issuecomment-1201663658
And in documentation:
https://devblogs.microsoft.com/typescript/announcing-typescript-4-7/#package-json-exports-imports-and-self-referencing
So, it works. I checked it by manually making changes to the package.
"exports": {
".": {
"require": {
"types": "./index.d.ts",
"default": "./index.js"
},
"import": {
"types": "./index.d.mts", // Copy-Paste from the 'index.d.ts' file
"default": "./index.mjs"
}
},
"./package.json": "./package.json"
},
For default import to work without esModuleInterop
option, .cjs
files must have exports like:
const fn = () => {};
module.exports = fn;
module.exports.default = fn;
See an example of changing build process