Description
π Search Terms
hybrid
commonjs
esm
module
moduleResolution
package.json
π Version & Regression Information
- This changed between versions 5.1 and 5.2
β― Playground Link
No response
π» Code
src/index.ts
export const foo = 'bar'
tsconfig.json
{
"include": ["src/*.ts"],
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"inlineSources": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"target": "es2022",
"moduleResolution": "nodenext",
"module": "nodenext"
}
}
tsconfig/cjs.json
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node16",
"outDir": "../dist/cjs"
}
tsconfig/esm.json
"compilerOptions": {
"outDir": "../dist/mjs"
}
package.json
{
"name": "foo",
"version": "1.2.3",
"type": "module",
"exports": {
".": {
"import": {
"types": "./dist/mjs/index.d.ts",
"default": "./dist/mjs/index.js"
},
"require": {
"types": "./dist/cjs/index.d.ts",
"default": "./dist/cjs/index.js"
}
}
},
"scripts": {
"prepare": "tsc -p tsconfig/cjs.json && tsc -p tsconfig/esm.json && bash scripts/fixup.sh"
}
}
scripts/fixup.sh
#!/usr/bin/env bash
cat >dist/cjs/package.json <<!EOF
{
"type": "commonjs"
}
!EOF
cat >dist/mjs/package.json <<!EOF
{
"type": "module"
}
!EOF
π Actual behavior
tsconfig/cjs.json:4:15 - error TS5110: Option 'module' must be set to 'Node16' when option 'moduleResolution' is set to 'Node16'.
π Expected behavior
Should create a CommonJS module at ./dist/cjs/index.js
.
Should create an ESM module at ./dist/mjs/index.js
Should not emit errors.
I also tried setting the module
to node16
in the cjs.json
, but then it emits ESM for the CJS build.
If I remove "type": "module"
from the root package.json (first of all, that's a pain, because my tests are ESM, but w/e), then it emits CommonJS for both.
If it's going to force module
to match moduleResolution
, and infer the type from the package.json
file, then it should infer the type from the package.json file that is closest to the build location, not the source location, because that is where Node will get the type from.
Better yet, it should just allow CommonJS even if the package.json is "type": "module"
and has a "require"
export point.
Or just trust that the author of the config file knows what they're doing, and obey the explicitly stated config. If someone writes "module": "commonjs"
, then TSC should emit a commonjs module, regardless of what the package.json's type
is.
Additional information about the issue
The only workaround I can see right now is to have my build script edit the root package.json
(or write a package.json
temporarily in ./src
) in between each build, and that just feels terribly brittle.