Repository navigation
TypeScript module "Node16" does not resolve types of CJS module #49160
Description
Activity
To expand on this, TypeScript 4.7.1-rc with
nodenextmodule resolution is unable to resolve various NPM dependencies. See this example repo.https://github.com/scott-lc/tsc-nodenext
npm install npm run buildWith
moduleandmoduleResolutionset tonodenext, it won't compile:src/test.ts:2:31 - error TS7016: Could not find a declaration file for module 'is-plain-object'. '/Users/ssadler/Code/livecontrol.io/tsc-nodenext/node_modules/is-plain-object/dist/is-plain-object.mjs' implicitly has an 'any' type. Try `npm i --save-dev @types/is-plain-object` if it exists or add a new declaration (.d.ts) file containing `declare module 'is-plain-object';` 2 import { isPlainObject } from "is-plain-object"; ~~~~~~~~~~~~~~~~~ src/test.ts:7:17 - error TS2351: This expression is not constructable. Type 'typeof import("/Users/ssadler/Code/livecontrol.io/tsc-nodenext/node_modules/decimal.js/decimal")' has no construct signatures. 7 console.log(new Decimal(123.4567)); ~~~~~~~Setting
moduletoesnextandmoduleResolutiontonode(as in pre-4.7), works fine.colorsdoes not havetypesdefined in itspackage.jsonfile. I believe the compiler will fallback to looking for a.d.tsfile in the same directory as themainfile, which in this case islib/index.d.js:{ "main": "lib/index.js", }Unfortunately in the
colorspackage, the corresponding "index.d.ts" is at the root of the repository, not at./lib/index.d.js. Either 1) adding an explicittypesproperty to thepackage.jsonor 2) moving the types to./lib/index.d.js"fixes" the problem.Seeing that colors has not been updated in 3 years but still gets 21M downloads a week means that a lot of developers are going to run into this issue. Should the TypeScript compiler support this use case or is it going to be up to the Node/NPM community to update existing packages that don't exactly conform to the
nodenexttype definition specification?I've also declaration reference issues for external CommonJS packages after switching to
module: node16(with TS 4.7.2).Namely
telegrafandform-data-encoder, but these packages have explicit"types"references to.d.tsin theirpackage.jsonfiles.Can also reproduce Laurens Rietveld (@LaurensRietveld)'s issue with
import colors from "colors".Other CommonJS packages with inline declarations (e.g.
import del from "del") work on the other hand...- changed the title
[-]TypeScript module "Node16" does not resolve index.d.ts in root of CJS module[/-][+]TypeScript module "Node16" does not resolve types of CJS module[/+]on May 25, 2022 LaurensRietveld commented
on May 25, 2022 AuthorMore actionsThanks ulrichb
- I've updated the issue description and made it a bit less opinionated (as you showed that this isn't just about a missing
typesfield). I also added theform-data-encoderpackage in the MWE - I also updated the MWE so that we're using the latest 4.7 release
Reacted by ulrichb- I've updated the issue description and made it a bit less opinionated (as you showed that this isn't just about a missing
andrewbranch commented
on May 25, 2022 MemberMore actionsEvery one of the packages mentioned here is misconfigured. You already figured out the issue with colors. (Actually, I’m a little surprised that colors even works with
--moduleResolution node.) Both form-data-encoder and telegraf haveexportspointing tolib/index.jsbut no corresponding types for that entrypoint. Note thattypescorresponds tomainonly.main/typeswill be completely ignored by Node/TypeScript ifexportsis defined.While node16/nodenext was in preview over the last two releases, we made an effort to track down some of the most popular npm packages that have TypeScript typings and package.json
exportsand audit them for correctness, but it was inevitable that many more were going to go through a (hopefully brief) period of pain as more people start to use this mode. This is a big part of the reason we held node16/nodenext in preview—we were hoping people would start to try it, ask why their dependencies weren’t working, and we could help get a lot of this straightened out before we shipped the stable release. Please do file issues/PRs against these libraries; as some of the earliest adopters of this mode, you can really help make this smoother for the folks who start trying it out in the coming weeks and months. Thanks!Reacted by Jacob Ley, Joni Hämäläinen, fregante, Adrián Molina and Arend de BoerReacted by Brian Kim, Rick and Binh Nguyen- addedExternalRelates to another program, environment, or user action which we cannot control.Relates to another program, environment, or user action which we cannot control.
on May 25, 2022 LaurensRietveld commented
on May 25, 2022 AuthorMore actionsThanks Andrew, I get the rationale and the choice not to support incorrect metadata. The effect is a pity though, considering some packages (such as the colors package for known reasons) are not expected to be actively maintained.
If I understand correctly then we can consider this a "won't fix" (on typescript's side) and close this issueReacted by Tamas HegedusLaurensRietveld commented
on May 25, 2022 AuthorMore actionsA note for those using the colors package with yarn2+: the yarn patch functionality also works on package.json files. Depending on your usecase, this may be a way out when using dependencies like colors
Laurens Rietveld (@LaurensRietveld) Shouldn't we reopen this issue until the universe (including colors) gets migrated?
I just ran into this with [email protected] and [email protected]
I'd actually disagree with Andrew Branch (@andrewbranch)'s statement at #49160 (comment) . I think projects like errlop and commander were properly specified at the time they released those specific versions. Without the ability in open-source to migrate all packages that specify types, this is probably going to continue to be painful until a fallback is added that works with the current state of the world
(Commander was updated in v9.2.0 with support for the new resolution approach.)
Reacted by Andrew Branch and Adrián Molinaandrewbranch commented
on Aug 17, 2022 MemberMore actionsI didn’t say they were always misconfigured, but they’re misconfigured now 🤷. They opted to use package.json
exportsbefore TypeScript supported it, so they were kinda broken as soon as they did that, but with no real way to remedy it yet. Now that we do support it, it’s not surprising that some updates will be needed. Nobody is at fault for the misconfiguration, but there’s simply nothing we can do on our end that won’t break other stuff. If we add additional guesses/fallbacks, those will absolutely produce incorrect resolutions some of the time, and people will get incorrect type info and missing errors on stuff that will crash at runtime.Also, this is not known widely enough: all any package author has to do is put their
.d.tsfiles in the same directories as their.jsfiles, just liketscemits them by default. The only packages that are dealing with issues are ones that put their types in a separate folder for some reason..d.tsand.jsfiles are best friends. If you don’t separate them, you literally don’t have to put anything special at all in the package.json.But I also want to make sure that we have empathy for why people were using exports already. It seems to be the only way to support commonjs and esm in the same package. And I can see how it super desirable to make it easier for your package to be used in both node and the browser.
And I also think relying on the layout of where the .d.ts file is relative to the .js would lead to bloat/repetitiveness if you you’re trying to support both in the same package.
The concept of "misconfigured" is preposterous given that there is no standard for
package.json(the community has been asking for one for years and NPM refuses, and now there are too many hands in the cookie jar and none of them seem to want to work together).So the idea that something in package.json is "misconfigured" because it's old is simply wrong. If it worked before, then it's not misconfigured. An ecosystem tool has just chosen to break them.
After 10+ years in the Node scene the package.json nightmare has only gotten worse. I'm not sure what the solution is, but the fact is that
node16breaks imports in most non-trivial cases I've tried it.Reacted by Shayan Toqraee, Ondrej Beluský, Ryan Christian, Eran Boodnero, Mark Erikson, Will Crichton, U.w.U, Adrián Molina, Evgeni Dikerman, Binh Nguyen and 8 more- added a commit that references this issue
on May 7, 2023 - added a commit that references this issue
on Sep 16, 2023 - added a commit that references this issue
on May 18, 2026
Bug Report
🔎 Search Terms
NodeNext, esm, CJS, colors
🕗 Version & Regression Information
⏯ Playground Link
I didn't include a playground link, as I can't reference dependencies there.
See here for an MWE.
To test:
💻 Code
🙁 Actual behavior
TypeScript cannot find the typings for some CommonJS packages such as colors and form-data-encoder
As a result, I'm getting this error:
🙂 Expected behavior
ESM module behaviour to import CJS as it used to.
Related
#47848