Fix wrong auto imports in TypeScript monorepo

Viewed 875

I have a TypeScript mono repository with the following basic file layout:

├── packages/
│   ├── workspace-a/
│   │   ├── src/
│   │   └── tsconfig.json
│   └── workspace-b/
│       ├── src/
│       └── tsconfig.json
└── tsconfig.json

The root tsconfig.json looks like this (with irrelevant properties stripped):

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@scope/*": ["packages/*/src"]
    },
    "module": "es2020",
    "moduleResolution": "node"
  }
}

tsconfig.json for each package looks like this:

{
  "extends": "../../tsconfig"
}

All packages use the @scope scope. This setup makes the following code work from workspace-a, as expected:

import { Foo } from '@scope/workspace-b';

However, the following code works too according to tsc and is suggested by auto imports in VSCode first:

import { Foo } from '@scope/workspace-b/src';
import { Bar } from 'packages/workspace-b/src';

The latter doesn’t work once packages are published to npm, causing issues after the packages have been published.

Can I make TypeScript disallow the latter? I’ll accept a solution involving an existing ESLint rule as well.

The full source code can be found here.

1 Answers

This issue is caused by the baseUrl option. This was previously needed when using the paths option.

As of TypeScript 4.1 paths can be used without baseUrl.

So the tsconfig.json would look like this:

{
  "compilerOptions": {
    "paths": {
      "@scope/*": ["./packages/*/src"]
    },
    "module": "es2020",
    "moduleResolution": "node"
  }
}

Omitting the baseUrl is not yet supported by tsconfig-paths, which is also used by various popular TypeScript related packages, such as:

Note that if you use tsconfig-paths for "paths" to work with ts-node, you must explicitly specify "baseUrl" with it because it does not yet support unspecified baseUrl.

Related