Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save oleshkooo/a403dc8b85e98070fb39844dfb3c0208 to your computer and use it in GitHub Desktop.
Save oleshkooo/a403dc8b85e98070fb39844dfb3c0208 to your computer and use it in GitHub Desktop.
The easiest way to set up absolute paths in your TypeScript Node.js project

The easiest way to set up absolute paths in your TypeScript Node.js project

Step-by-step guide. Works with Nest.js, Express.js or any other Node.js project. I'm going to show you how to do this quickly and easily, so let's get started.


Configure absolute paths

  1. Initialize the new package in the terminal if you haven't already done so:
npm init -y

yarn init -y

Your package.json should look something like this:

{
    "name": "absolute-paths",
    "version": "1.0.0",
    "main": "index.js",
    "license": "MIT"
}

  1. Similarly with tsconfig:
npx tsc --init

And don't forget to install typescript as devDependency:

npm i -D typescript @types/node

yarn add -D typescript @types/node

  1. Now let's install the necessary dependencies:
npm i -D ts-node ts-patch tsc-alias tsconfig-paths typescript-transform-paths

yarn add -D ts-node ts-patch tsc-alias tsconfig-paths typescript-transform-paths

  1. Next, you need to customize tsconfig.json a bit:

tsconfig.json

{
    "compilerOptions": {
        ...,
        "baseUrl": "src" /* Specify the base directory to resolve non-relative module names. */,
        "paths": {
            "@/*": ["*"]
        } /* Specify a set of entries that re-map imports to additional lookup locations. */,

        "plugins": [
            /* Transform paths in output .js files */
            {
                "transform": "typescript-transform-paths"
            },
            /* Transform paths in output .d.ts files */
            {
                "transform": "typescript-transform-paths",
                "afterDeclarations": true
            }
        ],
        ...
    }
}

  1. After that, add a few scripts to the package.json file:

package.json

{
    ...,
     "scripts": {
        "ts-prepare": "ts-patch install -s",
        "start:dev": "npm run ts-prepare && ts-node ./src/index.ts",
        // or
        "start:dev": "yarn ts-prepare && ts-node ./src/index.ts",
        "start:prod": "node ./build/index.js",
        "build": "tsc && tsc-alias"
    },
    ...
}

Before running the code in development mode, you need to run the ts-prepare command, and for a successful build, after it, run tsc-alias


  1. That's it! You can now use absolute paths in your project. You can also see some code examples below.

Code example

Project file structure

├── package.json
├── src
│   ├── dir
│   │   └── file.ts
│   └── index.ts
└── tsconfig.json

package.json

{
    "name": "absolute-paths",
    "version": "1.0.0",
    "main": "index.js",
    "license": "MIT",
    "scripts": {
        "ts-prepare": "ts-patch install -s",
        "start:dev": "npm run ts-prepare && ts-node ./src/index.ts",
        // or
        "start:dev": "yarn ts-prepare && ts-node ./src/index.ts",
        "start:prod": "node ./build/index.js",
        "build": "tsc && tsc-alias"
    },
    "devDependencies": {
        "@types/node": "^20.5.0",
        "ts-node": "^10.9.1",
        "ts-patch": "^3.0.2",
        "tsc-alias": "^1.8.7",
        "tsconfig-paths": "^4.2.0",
        "typescript": "^5.1.6",
        "typescript-transform-paths": "^3.4.6"
    }
}

tsconfig.json

{
    "compilerOptions": {
        "target": "es2017" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
        "module": "commonjs" /* Specify what module code is generated. */,
        "outDir": "build" /* Specify an output folder for all emitted files. */,
        "strict": true /* Enable all strict type-checking options. */,
        "skipLibCheck": true /* Skip type checking all .d.ts files. */,

        /* IMPORTANT */

        "baseUrl": "src" /* Specify the base directory to resolve non-relative module names. */,
        "paths": {
            "@/*": ["*"]
        } /* Specify a set of entries that re-map imports to additional lookup locations. */,

        "plugins": [
            /* Transform paths in output .js files */
            {
                "transform": "typescript-transform-paths"
            },
            /* Transform paths in output .d.ts files */
            {
                "transform": "typescript-transform-paths",
                "afterDeclarations": true
            }
        ]

        /* End of IMPORTANT */
    },
    "ts-node": {
        "transpileOnly": true,
        "files": true
    },
    "include": ["src/**/*"],
    "exclude": ["node_modules", "build"]
}

/src/index.ts

import { someData } from '@/dir/file'

console.log(someData)

/src/dir/file.ts

export const someData = 'some data'

Run (dev)

npm run start:dev

yarn start:dev

Output

npm

absolute-paths $ npm run start:dev

> absolute-paths@1.0.0 start:dev
> npm run ts-prepare && ts-node ./src/index.ts


> absolute-paths@1.0.0 ts-prepare
> ts-patch install -s

some data

yarn

absolute-paths $ yarn start:dev
$ yarn ts-prepare && ts-node ./src/index.ts
$ ts-patch install -s

some data

✨  Done.

Build

npm run build

yarn build

Output

npm

absolute-paths $ npm run build

> absolute-paths@1.0.0 build
> tsc && tsc-alias

yarn

absolute-paths $ yarn build
$ tsc && tsc-alias

✨  Done.

Run (build)

npm run start:prod

yarn start:prod

Output

npm

absolute-paths $ npm run start:prod

> absolute-paths@1.0.0 start:prod
> node ./build/index.js

some data

yarn

absolute-paths $ yarn start:prod
$ node ./build/index.js

some data

✨  Done.
@ghana7989
Copy link

Wow it worked seamlessly, Thanks for this.

@mohasinkr
Copy link

mohasinkr commented Jun 2, 2024

Can't believe we one has to go through all this and install a host of packages just to be able to use absolute imports?!

@oleshkooo
Copy link
Author

oleshkooo commented Jun 4, 2024

Yeah, but unfortunately otherwise either the project itself or the build will not work. At least, this is the only working way I know

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment