Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reconcile monorepo with multiple tsconfig.json each having its own paths?

We have a codebase setup like so:

-A
--utils
---index.ts
--index.ts
--tsconfig.json
-B
--utils
---index.ts
--index.ts
--tsconfig.json
-tsconfig.json

Our root tsconfig.json contains the following:

    "paths": {
      "A/*": ["A/*"],
      "B/*": ["B/*"],
    },

Each package's tsconfig.json contains the following:

    "paths": {
      "utils/*": ["./utils/*"],
    },

This works for our current purposes, since we currently only use TS for type checking but we actually generate builds with Babel, which has a similar setup in the alias property of the various .babelrc files.

We are looking to start running code using ts-node (or an equivalent) and have run into the issue that at runtime, TS has no idea how to resolve modules. For example:

// A/index.ts
import { someUtil } from 'utils'
export const someFunc() => someUtil();
// B/index.ts
import { someFunc } from 'A';

When we run npx ts-node ./B/index.ts we get an error saying `Cannot find modules 'utils'.

We know that we can get this working by hoisting everything to the root tsconfig.json, but it seems superfluous to have to import { someUtil } from 'A/utils when you are already in package A.

Is there a way to use paths in the manner that we have? We have also read a bit about project references and tried that but it didn't seem to get us anywhere.

like image 919
Matthew Herbst Avatar asked Mar 24 '21 22:03

Matthew Herbst


2 Answers

Inside the tsconfig.json file in each of the projects you should use extends on the root tsconfig like this:

// A/tsconfig.json
{
 "extends": "../tsconfig.json",
 ...
}

Thay way all the subprojects will inherit the paths from other general packages.

I think you can even define the utils path on the root, that way you won't have to repeat that either.

More about the extends option here:

https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#tsconfig-bases

UPDATE

Also you need to use this lib:

https://www.npmjs.com/package/tsconfig-paths

and inside the package.json in the ts-node script in the scripts property you use: ts-node ... -r tsconfig-paths/register ... index.ts.

This lib will read the packages in ts-config.json and place them in node_modules, so your other packages can find them when you run with node or ts-node.

like image 143
WilsonPena Avatar answered Nov 14 '22 01:11

WilsonPena


I hope it's not rude or unhelpful to suggest what you're trying to do might make no sense.

From the point of view of package A, './utils' can be different from the './utils' that package B sees - since they have a different filesystem 'root'. However, the attempt to alias two different './utils' paths as 'utils' from the point of view of BOTH packages creates an inevitable collision.

I am far from sure there's any value in doing this either. I would personally drop the aliasing of folders "./utils" to top-level aliases "utils" and then I think your issues will go away. Probably what you want on a per-package basis is specific includes, and for the 'local' utils for each package to be addressed relatively to the package...

{
  "extends": "../tsconfig.json",
  "include": ["index.ts", "utils/index.ts"]
}
like image 1
cefn Avatar answered Nov 14 '22 01:11

cefn