-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Description
🔎 Search Terms
module resolver nodenext node16 commonjs module dual package error require import
Here are some similar issues:
- package.json
exports
resolution uses fallback conditions, unlike Node #50762 - Rethinking
module
for the present and the future #55221
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about module resolution
⏯ Playground Link
https://github.com/jthemphill/ts-cjs-repro
💻 Code
The "lib"
package in my repo is modeled after the popular project https://github.com/yjs/yjs. Like yjs, lib
uses Rollup to build CJS and ESM versions of the package, then uses TypeScript to emit a declaration file.
Its package.json
has a conditional export:
"exports": {
".": {
"types": "./dist/src/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
},
This enables the package to be either imported or required, whether from ESM or CJS files.
The app
package represents my project, which I am trying to move from {"module": "commonjs"}
to the more correct {"module": "node16"}
. Its index.ts
file is two lines:
import * as dual from "lib";
console.log(dual.dualCjsMjs);
You can reproduce the problem with
cd packages/app
pnpm install && pnpm build
🙁 Actual behavior
node app/dist/index.js
will run the code successfully. But TypeScript claims that the code will crash:
ts-cjs-repro/packages/app % pnpm build
> app@ build /Users/jhemphill/oss/ts-cjs-repro/packages/app
> tsc
index.ts:1:23 - error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("lib")' call instead.
To convert this file to an ECMAScript module, change its file extension to '.mts', or add the field `"type": "module"` to '/Users/jhemphill/oss/ts-cjs-repro/packages/app/package.json'.
1 import * as dual from "lib";
~~~~~
Found 1 error in index.ts:1
🙂 Expected behavior
TypeScript should not report an error here. Node is correctly importing index.cjs
, and this file really does contain the values described in index.d.ts
.
Additional information about the issue
I would like to migrate my team's project from the commonjs
resolver to the more correct node16
resolver, but it is hard to sell teammates on this migration if the "more correct" resolver leads to a bunch of false positives until we also complete an ESM migration😕
I understand why the module resolver thinks that index.d.ts
describes a module file, as the nearest package.json
contains a "type": "module"
field. This doesn't help me migrate my project, though.