vite-plugin-react: ts error when moduleResolution is "node16"
Describe the bug
I am migrating my node application from cjs to mjs. When I set "moduleResolution": "node16"
in tsconfig.json
, the vite.config.ts
reports This expression is not callable. Type 'typeof import("/node_modules/@vitejs/plugin-react/dist/index")' has no call signatures.ts(2349)
.
I tried to change reactPlugin()
to reactPlugin.default()
, the error disappears but vite build failed with error TypeError: reactPlugin.default is not a function
Reproduction
Steps to reproduce
set compilerOptions.moduleResolution = ‘node16’ in tsconfig.json
System Info
System:
OS: macOS 13.0.1
CPU: (8) arm64 Apple M1 Pro
Memory: 44.64 MB / 16.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 16.14.0 - ~/.nvm/versions/node/v16.14.0/bin/node
Yarn: 1.22.17 - ~/.nvm/versions/node/v16.14.0/bin/yarn
npm: 8.19.2 - ~/.nvm/versions/node/v16.14.0/bin/npm
Browsers:
Chrome: 109.0.5414.119
Firefox: 108.0.2
Safari: 16.1
npmPackages:
@vitejs/plugin-react: ^3.1.0 => 3.1.0
vite: ^4.1.1 => 4.1.1
Used Package Manager
npm
Logs
No response
Validations
- Follow our Code of Conduct
- Read the Contributing Guidelines.
- Read the docs.
- Check that there isn’t already an issue that reports the same bug to avoid creating a duplicate.
- Make sure this is a Vite issue and not a framework-specific issue.
- Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- The provided reproduction is a minimal reproducible example of the bug.
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 1
- Comments: 20 (7 by maintainers)
Every TypeScript resolution mode supports extension matching to sibling files. If every
index.mjs
has a siblingindex.d.mts
and everyindex.cjs
has a siblingindex.d.cts
and everyindex.js
has a siblingindex.d.ts
, then nothing in package.json needs to explicitly reference the declaration files. TypeScript can always figure it out by following the implementation file config and then looking for a sibling.If the types are not colocated with the implementation, or you just want to be explicit in the export map, you can use nested conditions:
Just note that this does not make it possible to reuse a single
.d.ts
for both the CJS and ESM entrypoint—the file extension and package.json"type": "module"
(or lack thereof) is the only thing that determines the module kind here, so a nested config likeis equivalent to what is published today. In other words, just because you reach a file via the
import
condition in an export map during a given resolution does not automatically make it an ES module; rather, a file’s module kind status is statically determined by information from the file system alone (its file extension and package.json"type"
). And again, let me stress that these are not our rules, they’re Node’s. We just apply Node’s algorithm to declaration files such that when each implementation file has a corresponding declaration file, we can predict what Node will do (which is obviously necessary to type check across multiple files). Don’t shoot the messenger 😅This is exactly why the TS team added the bundler resolution, so that TS resolutions is more close (and maybe totally identical when using pure esm with explicit extensions) to how bundler like Vite resolve modules.
So yeah you can now update TS to v5, and then update your TS config to use this new resolution, opt-in to
allowImportingTsExtensions
, removeforceConsistentCasingInFileNames
that is now true by default.Here is my config:
I will add a note in the readme to advice using this resolution algorithm.
Hi!
With the team we decided to not invest more time in the node16 resolutions issues. This IMO a bad design and this as been fixed with TS 5 bundler mode that more clearly represent how most apps and projects are built. If you’re not able to migrate, we recommend keeping the old “node” resolution algorithm.