Description
I have a problem in which path mapping is not flexible enough for different project scenarios.
I have the following project layout: I have separate main
and tests
directories which use different versions of the protobufjs
type definitions.
Project layout
/src
+-- tsconfig.base.json
+-- /main
+-- (sources…)
+-- tsconfig.json
+-- /tests
+-- (sources…)
+-- tsconfig.json
/node_modules
+-- /@types
+-- /protobufjs
+-- index.d.ts
The main sources should use the newer definitions that come included with the npm package, the tests use generated code that refers to an older and incompatible version of protobufjs
that uses the definitions from node_module/@types
. I therefore use the following path mapping, which works as intended:
/src/tsconfig.base.json
{
"compilerOptions": {
"rootDir": "./",
"baseUrl": "./",
}
}
/src/main/tsconfig.base.json
{
"extends": "../tsconfig.base.json",
"include": [
"**/*.ts"
]
}
/src/test/tsconfig.base.json
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"paths": {
"protobufjs": ["../node_modules/@types/protobufjs"],
}
},
"include": [
"**/*.ts"
]
}
The problem arises when I include this package in a yarn workspace. In this situation the node_modules
folder gets hoisted up one level, and since the path mappings are interpreted as being relative to baseUrl
, they do no longer resolve to a valid directory.
Quoting from the yarn documentation this seems an obvious problem:
The package layout will be different between your workspace and what your users will get (the workspace dependencies will be hoisted higher into the filesystem hierarchy). Making assumptions about this layout was already hazardous since the hoisting process is not standardized, so theoretically nothing new here.
I see two ways to resolve this problem:
-
Require paths to be interpreted as being relative to
baseUrl
to have a leading./
. Interpret path mappings without it as relative paths subject to node module resolution logic. This would require small fixes for many projects. -
Introduce a special leading signifier (e.g
^
) or add a special attribute incompilerOptions
(e.g.nodePaths
) for path mappings subject to node module resolution logic.