Description
🔎 Search Terms
"NodeNext", "ESNext", "Bundler", "module", "moduleResolution", "ESM", "CJS", "multi-project", "dual package"
🕗 Version & Regression Information
- This is the behavior in every version I tried (5.0.4, 5.1.6, 5.2.2, 5.3.3, and 5.5.0-dev.20240226), and I reviewed the FAQ for entries about ESM
⏯ Playground Link
https://github.com/haines/typescript-dual-package-esnext-bundler-nodenext
💻 Code
It's probably less confusing to look at the repo, sorry 🙈 I've tried to make it as minimal as possible.
This bug occurs in a multi-project build where one project (app
) is configured to use ESNext
module and Bundler
module resolution, and another (lib
) is using NodeNext
. Everything is set up to use ESM with "type": "module"
in package.json.
If both projects depend on the same dual-packaged dependency (dep
), then when app
imports dep
directly, TypeScript correctly resolves the ESM types. However, transitive imports of dep
through lib
are resolved to the CJS types.
🙁 Actual behavior
TypeScript resolves the CJS types for transitive imports of the dual-packaged dependency. If the CJS types are not perfectly compatible with the ESM types, then this causes compile errors.
🙂 Expected behavior
TypeScript resolves the ESM types for all imports of the dual-packaged dependency.
Additional information about the issue
Originally encountered in @bufbuild/protobuf
: bufbuild/protobuf-es#718
Our app
is full-stack and built with Vite, which is why we want to use ESNext/Bundler
, but our lib
is consumed by other Node.js-only projects that are built with tsc and therefore it makes sense for that to be built with NodeNext
.