Search code examples
typescripttsconfigmonorepo

Extend a "paths" tsconfig file for a monorepo


I've got a folder structure like so:

- mono-repo
  tsconfig.paths.json
  - Website
   tsconfig.json
   - src
     test.ts
     index.ts
  - Tool
   - src
    index.ts
// mono-repo/tsconfig.paths.json
{
  "compilerOptions": {
    "paths": {
      "tool": ["Tool/src"],
    }
  }
}
// mono-repo/Website/src/index.ts
import { test } from "test";
import { tool } from "tool";

test(tool);

I'd like to be able to extend tsconfig.paths.json so that every package has correctly typed module imports for the others.


Failed Attempt 1

// mono-repo/Website/tsconfig.json
{
  "extends": "../tsconfig.paths.json",
  "compilerOptions": {
    "baseUrl": "./src",
  }
}

Issue: can not find module "tool". The baseUrl added to the path leads to mono-repo/Website/src/Tool/src. This is not a real path.


Failed Attempt 2

// mono-repo/Website/tsconfig.json
{
  "extends": "../tsconfig.paths.json",
  "compilerOptions": {
    "baseUrl": "../",
  }
}

Issue: can not import test from "test". The baseUrl is not the project src. Anything but relative paths will be unexportable.


Functional but Ugly Attempt 3

// mono-repo/tsconfig.paths.json
{
  "compilerOptions": {
    "paths": {
      "tool": ["../../Tool/src"],
    }
  }
}
// mono-repo/Website/tsconfig.json
{
  "extends": "../tsconfig.paths.json",
  "compilerOptions": {
    "baseUrl": "./src",
  }
}

Issue: works, but makes the assumption that the baseUrl of every tsconfig which extends tsconfig.paths.json will always be two directories below mono-repo. This is currently true for my project, but I'm hesitant to make this a standard.


How does one set up an extendable "paths" tsconfig json for a monorepo?


Solution

  • Something to know is that tsconfig extends is an override and not a merge. With that information, you can understand that what you are trying to achieve by extending the base tsconfig can't work as you expecting it to do.

    Also, using the paths options should always work as a pair with the baseUrl in order to solve the resolution problem.

    Nonetheless, here is a solution that you can use to solve that problem.

    create a tsconfig.json at the root level of your project alongs the line of:

    "paths": {
      "~/*": ["../../../mono-repo/*/src"]
    }
    

    Which means in each sub packages, you can extends that tsconfig file and then specify your src directory as a baseUrl. Then you will be able to import as follow:

    import { tool } from "~/Tool";
    

    Hope that it is clear, let me know if something is missing =)