I have a NodeJS monorepo set up using NPM workspaces and Typescript. It works fine without Typescript, however introducing TS brings some dependency resolving errors with it. Current directory setup:
+-- node_modules
+-- package.json
+-- tsconfig.json
+-- tsconfig.build.json
+-- packages
+-- core
| +-- package.json
| +-- tsconfig.json
| +-- src
| +-- index.ts
+-- shared
| +-- package.json
| +-- tsconfig.json
| +-- src
| +-- helper.ts
Running npm ls
confirms that everything has been symlinked up correctly:
[email protected] C:\Users\<user>\Documents\Temp\monorepoDemo
├─┬ @my-packages/[email protected] -> .\packages\core
│ └── @my-packages/[email protected] deduped -> .\packages\shared
└── @my-packages/[email protected] -> .\packages\shared
I've got a dummy helper function being exported from helper.ts
in shared
. Which is being imported into index.ts
in core
. The root package.json
, tsconfig.ts
and tsconfig.build.json
:
{
"name": "monorepoDemo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node packages/core/src/index.ts",
"test": "echo \"Error: no test specified\" && exit 1",
"build": "tsc -b --verbose tsconfig.build.json"
},
"author": "",
"license": "ISC",
"workspaces": [
"packages\\core",
"packages\\shared"
]
}
{
"compilerOptions": {
"composite": true,
"target": "es2021",
"module": "commonjs",
"declaration": true,
"declarationMap": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
{
"files": [],
"references": [
{
"path": "packages/core"
},
{
"path": "packages/shared"
}
]
}
The package.json
and tsconfig.json
of core
:
{
"name": "@my-packages/core",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@my-packages/shared": "^1.0.0"
}
}
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist",
"baseUrl": ".",
"paths": {
"@my-packages/shared": ["../shared"]
}
},
"references": [{ "path": "../shared" }],
"exclude": ["dist"]
}
The package.json
and tsconfig.json
of shared
:
{
"name": "@my-packages/shared",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
},
"exclude": ["dist"]
}
And the source code of index.ts
and helper.ts
:
import { helper } from "@my-packages/shared"
(async () => {
console.log("Bootstrapping from core package")
helper()
})()
export function helper(): void {
console.log("Running from shared package")
}
The error I get in index.ts
:
Cannot find module '@my-packages/shared' or its corresponding type declarations.ts(2307)
I assumed it was something related to a missing declaration file, so tried to create one for helper.ts
but didn't get anywhere
The main
field of package.json
file is the entry point when other packages (like core
) imports the package:
import { helper } from "@my-packages/shared"
This code will try to look for @my-packages/shared/index.js
, which does not exist.
When you build the shared package, the built file is at dist/helper.js
.
Changing the main field to "main": "dist/helper.js"
made it work. If you are using vscode, don't forget to restart the language server.
For other considerations, like specific compiler options or esm support, consult the document ECMAScript Modules in Node.js.
The project monorepoDemo
should use the project @my-packages/core
that is built, in your case in the (sharedDir)/dist
directory.
In order for typescript to find the package @my-packages/core
when parsing monorepoDemo
typescript files, you have to specify where this package is located in the monorepoDemo
's tsconfig.json file:
"compilerOptions": {
"allowJs": true,
"paths": {
"@my-packages/shared": ["(sharedDir)/dist"],
After that make sure the library is built and the (sharedDir)/dist
folder created.
If there are several projects that use @my-packages/shared
, you can create a single tsconfig.libs.ts
file that contains all libraries locations, and add an extends
property into tsconfig.ts
of projects to tsconfig.libs.ts
:
{
"extends": "../../tsconfig.lib.json",
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With