I encountered this issue recently and felt pretty silly when I realized the simple mistake I was making, so allow me to share, in hopes that it saves someone else time...
When you're developing an NPM package that makes use of a dependency also used by the main application, you might consider listing it as a peer dependency.
Take this example, where we move React from "dependencies" to "peerDependencies":
- "dependencies": {
- "react": "^16.8.4 || ^17.0.0"
- },
"devDependencies": {
"@docusaurus/theme-classic": "^2.0.1",
"@types/react": "^18.0.17"
+ },
+ "peerDependencies": {
+ "react": "^16.8.4 || ^17.0.0"
}
React is now a peer dependency, which means the main application needs to list it in its own dependencies. Additionally, we're able to keep developing this package with no issues from TypeScript (can you see why?).
Now notice that other package, @docusaurus/theme-classic
. I wanted to make this one a peer dependency as well, so I did just that:
"devDependencies": {
- "@docusaurus/theme-classic": "^2.0.1",
"@types/react": "^18.0.17"
},
"peerDependencies": {
+ "@docusaurus/theme-classic": "^2.0.1",
"react": "^16.8.4 || ^17.0.0"
}
}
But after I made this change, TypeScript wasn't happy. 😔 When I tried importing from that module I got the typical "Cannot find module or its corresponding type declarations" error. I spent quite a while scratching my head, trying to understand peer dependencies. I knew package manager CLIs don't automatically install peer dependencies, but I couldn't figure out why other packages, such as React, were working while this one wasn't.
And this is where I felt silly after figuring it out: the @docusaurus/theme-classic
package was supplying its own type declarations, so moving it over to peer dependencies was eliminating its types altogether.
To address this, the simplest solution I've found is to duplicate that dependency over to "devDependencies". Doing this makes sure that it is installed locally while you develop the package, while also maintaining its status as a peer dependency when the main application consumes it.
"devDependencies": {
+ "@docusaurus/theme-classic": "^2.0.1",
"@types/react": "^18.0.17"
},
"peerDependencies": {
I've also tried playing with the install-peers package, that claims to install all your peer dependencies as dev dependencies, but wasn't having much success with it.
If you have your own solution for this problem, I'd love to hear it!
Top comments (2)
Very nice article. Helped me understand my problem better.
Encountered the same issue! Anyone has any ideas how to work around it?