I'm currently running a backend application in Typescript 5.2, which can be build to run as a Debian service on production with node 18 or directly run in a Docker container through nodemon.
Everywhere in my app you can find relative imports, sometimes short, sometimes very long:
import { Shortcut } from './Shortcut';
import { formatQuery } from '../../../../../../helpers/formatQuery';
And I would like to get rid of these imports.
My package.json
looks like:
{
"name": "toto",
"version": "1.4.9",
"description": "tata",
"scripts": {
"start:dev": "nodemon --config ./node_modules/@titi/config/nodemon.json",
"build": "tsc -p tsconfig.json"
},
"devDependencies": {
"jest": "29.6.1",
"ts-jest": "29.1.0",
"typescript": "5.2.2"
},
"dependencies": {
"nodemon": "3.0.1",
},
"volta": {
"node": "18.17.0",
"yarn": "1.22.17"
}
}
I use a custom nodemon.json
which is:
{
"watch": ["src/", "*.json"],
"ignore": [
".git",
"public",
"node_modules/**/node_modules",
"src/**/*.test.*",
"src/**/*.spec.*"
],
"ext": "ts,js,json",
"exec": "tsc -p tsconfig.json --incremental && node --trace-warnings --trace-uncaught build || exit 1"
}
and finally, my tsconfig.json
file look like this:
{
"compilerOptions": {
"lib": ["es2020"],
"module": "commonjs",
"target": "es2020",
"moduleResolution": "node",
"outDir": "../../../build",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"allowSyntheticDefaultImports": true,
"downlevelIteration": true,
"declaration": true,
"sourceMap": true,
"pretty": true,
"baseUrl": ".",
"paths": {
"@services/*": [
"src/services/*"
],
"@routes/*": [
"src/routes/*"
],
"@helpers/*": [
"src/helpers/*"
]
},
},
"files": ["../../../src/index.ts"],
}
I already know a lot of solutions do exists, I already tried a lot of them but none worked, like:
Setting the
baseUrl
property
No matter if I set it to .
or ./src
in my tsconfig.json
, I can't start my project and I keep getting this error:
import { formatQuery } from 'src/helpers';
src/services/toto.ts:5:29 - error TS2307
: Cannot find module 'src/helpers' or its corresponding type declarations.
Adding
paths
properties to thetsconfig.json
Whenever I set a paths
property, it's being ignored. For example:
"@helpers/*": [ "src/helpers/*" ]
and import a function like this result to:
import { formatQuery } from '@helpers';
src/services/toto.ts:5:29 - error TS2307
: Cannot find module '@helpers' or its corresponding type declarations.
(and that even if I put @helpers/formatQuery
, and even with a BaseUrl
to .
)
using the
NODE_PATH
env variable
Since BaseUrl
and paths
properties change the compiled files (javascript), you can't expect JavaScript to know where is the BaseUrl, so I tried to use this env variable in my nodemon.json
's "exec" like:
"exec": "tsc -p tsconfig.json --incremental && NODE_PATH=src node --trace-warnings --trace-uncaught build || exit 1"
Changing my IDE settings (for both JS and TS)
I'm currently using VSCode, and I read somewhere that I needed to edit the typescript.preferences.importModuleSpecifier
variable to non-relative
(even if I'm not fond of this way, because it globally means new developers that will works on my project won't be abble to make it works if they don't set this property in their VSCode ?)
Using new SubPath pattern
Adding a
jsconfig.json
I tried to add a jsconfig.json
file with baseUrl
and paths
property as put in the tsconfig.json
, but it didn't worked.
EDIT: I just forget to tell that the file src/helpers/index.ts
do exists, and for clarity sake I'm adding here it's content:
export * from './parseString';
export * from './formatQuery';
...
So what am I doing wrong ? is my architecture too complex to use non-relative imports ?
You need to do some little changes on
baseUrl
andpaths
:On paths you don't need to add
src
becausebaseUrl
is making paths to start from this folder. If you add it thents
will search for/src/src/....
and this is not the case. Read more here.After setting
paths
you need to usetsc-alias
so@helpers/XXX
will be correctly converted to the actual path of file after typescript build. See this for more details.