I've read and attempted to apply answers to many variations of this question on SO.
I made a very simple project as PoC, just to finally get tsconfig.ts
options right.
Nothing works. VSCode highlights an error in my imports w/o changes to config. But, even when VSCode is satisfied this will not run/compile. I don't have any of these issues with non-relative paths in a JS project and have read all documentation around this to no avail.
Environment: TSC 4.6.2, NodeJS 16.13.1, on Mac OS Monterey.
Simple ts-hello-world
project structure:
./
node_modules/
package.json
tsconfig.json
src/
data/
string.ts -> exports message
utils/
punctuation.ts -> exports exclamation
main/
app.ts -> imports message and puncutation and concats to display "Hello, World!"
package.json
{
"devDependencies": {
"ts-node": "^10.7.0"
}
}
string.ts
export const message: string = 'Hello, World';
punctuation.ts
export const exclamation: string = '!';
main.ts (made sure this works with relative paths)
import { message } from 'data/string';
import { exclamation } from 'utils/punctuation';
const howdy: string = message exclamation;
console.log(howdy);
tsconfig.json In a simple form that satisfies VSCode/works in CMD Click to follow/open imports.
{
"compilerOptions": {
"moduleResolution": "node",
"baseUrl": "./src",
"paths": {
"data/*": ["data/*"],
"utils/*": ["utils/*"]
}
}
}
I hope somebody can present a working answer! I've tried to revisit this so many times! I have tried all the answers, including prefixing paths with @
, rootDir, paths with "src/*" and baseUrl ".", and on and on. I've tried all the accepted answers on all the questions remotely around this. TS documentation didn't help. What am I missing?
CodePudding user response:
tsc node
With baseUrl
, you're telling Typescript to base all your modules from a specific directory. Which means they will also be compiled with paths relative to baseUrl
. It is expected that you then use some bundling tool that does all the resolution magic. But node
doesn't know anything about this, node
is not aware of tsconfig.json
, so it will try to find these modules in the path relative to the script and relative to NODE_PATH
env variable.
$ npx tsc && node src/main/app.js
Error: Cannot find module 'data/string'
So the solution would be to pass NODE_PATH
before running, like this:
$ npx tsc && NODE_PATH=src node src/main/app.ts
Hello, World!
Also, with your current tsconfig.json
, you don't really need "paths" section. The config I used for tests above:
{
"compilerOptions": {
"target": "ESNext",
"module": "CommonJS",
"moduleResolution": "node",
"baseUrl": "./src"
}
}
ts-node
Now, why doesn't it work with ts-node
? It should be aware of tsconfig.json
, right? The reason why it doesn't work "out-of-the-box", is explained in their docs:
This means "paths" are intended to describe mappings that the build tool or runtime already performs, not to tell the build tool or runtime how to resolve modules. In other words, they intend us to write our imports in a way node already understands. For this reason, ts-node does not modify node's module resolution behavior to implement "paths" mappings.
But they have a solution for this, you should install tsconfig-paths
plugin and add it to the tsconfig.json
:
{
...
"ts-node": {
// Do not forget to `npm i -D tsconfig-paths`
"require": ["tsconfig-paths/register"]
}
}
$ npm i -D tsconfig-paths
added 5 packages, and audited 23 packages in 2s
$ npx ts-node src/main/app.ts
Hello, World!