TypeScript: Intellisense not resolving modules when using `exports` in package.json
Reposting from VSCode repo for @magnusriga. I transferred the original issue to the wrong repo and now can’t transfer it back
Does this issue occur when all extensions are disabled?: Yes
- VS Code Version: 1.84.2
- OS Version: Windows 11 Pro
Steps to Reproduce:
- Build any project (A) with a dependency on another project (B), where project B’s package.json exports files using the
exportsfield - Observer how Intellisense does not work
- Insert the
mainandtypesfields and see that Intellisense starts working again
Intellisense Works When main and types are set:
Package B’s package.json
Package A’s import (notice the Intellisense pop-up. It is possible to ctrl-click the path.)
Intellisense Does Not Work When only exports is set:
Package B’s package.json (removed main and types)
Package A’s import (not possible to crl+click to find the package, i.e. no Intellisense)
About this issue
- Original URL
- State: closed
- Created 8 months ago
- Reactions: 1
- Comments: 34 (14 by maintainers)
Update to TypeScript 5.4 when it comes out. #56946
Yes, I’ll try that out and see if there are any objections.
This is working as intended. JavaScript files imported from
node_modulesare not analyzed for type information by default.This appears to be a bug.
That’s correct, at least according to the
exportsspec written by Node.js, which is what TS tries to follow. Some bundlers may be more flexible than this but there is some ongoing discussion about making those bundler resolvers conform to the spec in future major version bumps. Neither option is better practice than the other. It’s up to you.@virtuallyunknown What you say makes complete sense, but I couldn’t find any other good way to remove that ESLint error you mentioned, which I got when importing a JS file into a TS file. Obviously the JS file does not have type declarations in the first place, so ideally it should not check that file when it sees that it is JS and not TS.
Other suboptimal ways the remove the error included changing
stricttofalsein tsconfig, or placing@ts-expect-errorabove the import. None of these seem viable.What’s happening here is the presence of the
tsconfig.jsonnext totest.jsis throwing us off from finding the rootjsconfig.jsonwhen looking for a config to use for editor support. When you opentest.js, we start looking for jsconfig/tsconfig files up the directory spine from that file. We stop when we see the tsconfig.json, but it doesn’t actually include test.js. Instead of continuing the search, it seems like we give up and put test.js in an inferred project with default settings. I don’t know if this is a known limitation or a bug, but it seems like something that could be improved. (cc @sheetalkamat)I think the most conventional workaround would be to put your scripts in their own directory with their own tsconfig.json/jsconfig.json. Alternatively, you could name your package-level tsconfigs something else (tsconfig.src.json) and reference them from a root-level solution tsconfig.json:
The trick is to make it so that the nearest file named literally
tsconfig.json(orjsconfig.json) up from any file actually includes that file somehow, either directly or by fanning out into a referenced project that includes it.@andrewbranch thanks for taking your time to explain the issue to me, I really appreciate it.
I have tried the
jsconfig.jsonand it seems to do the trick, so I suppose this is an acceptable workaround for the time being (or alternatively using main field), and if you and/or the vscode team are aware of the issue, then that’s great.In my personal opinion it’s important that developers can make use of all ESM features so we can finally move away from CJS and all start using one unified system, but I also understand you guys probably have more pressing issues that require your attention.
Cheers!
@virtuallyunknown this is a known issue regarding the default settings that VS Code passes to TS Server (which powers JavaScript IntelliSense). The current defaults are very forgiving, which is good because we don’t know what kind of project a JS user has without additional config, but they lack support for newer features like package.json
"exports". If this is a Node.js project, you can add ajsconfig.jsonfile to your project root like this:@andrewbranch I actually got it to work. I posted a working repo above to showcase the settings needed to make it work (in case it is useful to others in the future).
@mjbvz can mark it as resolved (I am unable to, since I am no longer the OP).