How to use paths in tsconfig.json?

TypescriptNode ModulesTsconfig

Typescript Problem Overview


I was reading about path-mapping in tsconfig.json and I wanted to use it to avoid using the following ugly paths:

enter image description here

The project organization is a bit weird because we have a mono-repository that contains projects and libraries. The projects are grouped by company and by browser / server / universal.

enter image description here

How can I configure the paths in tsconfig.json so instead of:

import { Something } from "../../../../../lib/src/[browser/server/universal]/...";

I can use:

import { Something } from "lib/src/[browser/server/universal]/...";

Will something else be required in the webpack config? or is the tsconfig.json enough?

Typescript Solutions


Solution 1 - Typescript

This can be set up on your tsconfig.json file, as it is a TS feature.

You can do like this:

"compilerOptions": {
        "baseUrl": "src", // This must be specified if "paths" is.
         ...
        "paths": {
            "@app/*": ["app/*"],
            "@config/*": ["app/_config/*"],
            "@environment/*": ["environments/*"],
            "@shared/*": ["app/_shared/*"],
            "@helpers/*": ["helpers/*"]
        },
        ...

Have in mind that the path where you want to refer to, it takes your baseUrl as the base of the route you are pointing to and it's mandatory as described on the doc.

The character '@' is not mandatory.

After you set it up on that way, you can easily use it like this:

import { Yo } from '@config/index';

the only thing you might notice is that the intellisense does not work in the current latest version, so I would suggest to follow an index convention for importing/exporting files.

> https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping

Solution 2 - Typescript

You can use combination of baseUrl and paths docs.

Assuming root is on the topmost src dir(and I read your image properly) use

// tsconfig.json
{
  "compilerOptions": {
    ...
    "baseUrl": ".",
    "paths": {
      "lib/*": [
        "src/org/global/lib/*"
      ]
    }
  }
}

For webpack you might also need to add module resolution. For webpack2 this could look like

// webpack.config.js
module.exports = {
    resolve: {
        ...
        modules: [
            ...
            './src/org/global'
        ]
    }
}

Solution 3 - Typescript

Check this similar solutions with asterisk

  "baseUrl": ".",
  "paths": {
    "*": [
      "node_modules/*",
      "src/types/*"
    ]
  },

Solution 4 - Typescript

If you are using paths, you will need to change back absolute paths to relative paths for it to work after compiling typescript into plain javascript using tsc.

Most popular solution for this has been tsconfig-paths so far.

I've tried it, but it did not work for me for my complicated setup. Also, it resolves paths in run-time, meaning overhead in terms of your package size and resolve performance.

So, I wrote a solution myself, tscpaths.

I'd say it's better overall because it replaces paths at compile-time. It means there is no runtime dependency or any performance overhead. It's pretty simple to use. You just need to add a line to your build scripts in package.json.

The project is pretty young, so there could be some issues if your setup is very complicated. It works flawlessly for my setup, though my setup is fairly complex.

Solution 5 - Typescript

This works for me:

 yarn add --dev tsconfig-paths

 ts-node -r tsconfig-paths/register <your-index-file>.ts

This loads all paths in tsconfig.json. A sample tsconfig.json:

{
    "compilerOptions": {
        {}
        "baseUrl": "./src",
        "paths": {
            "assets/*": [ "assets/*" ],
            "styles/*": [ "styles/*" ]
        }
    },
}

Make sure you have both baseUrl and paths for this to work

And then you can import like :

import {AlarmIcon} from 'assets/icons'

Solution 6 - Typescript

Alejandros answer worked for me, but as I'm using the awesome-typescript-loader with webpack 4, I also had to add the tsconfig-paths-webpack-plugin to my webpack.config file for it to resolve correctly

Solution 7 - Typescript

If you are using tsconfig-paths and this does not work for you, try tsconfig.json:

{
  // ...
  "compilerOptions": {
    "outDir": "dist",
    "rootDir": "src",
    "baseUrl": ".",
    "paths": {
      "@some-folder/*": ["./src/app/some-folder/*", "./dist/app/some-folder/*"],
      // ...
    }
  },
  // ...
}

If the compiler sees @some-folder/some-class, it is trying to find it in ./src... or in ./dist....

Solution 8 - Typescript

Its kind of relative path Instead of the below code

import { Something } from "../../../../../lib/src/[browser/server/universal]/...";

We can avoid the "../../../../../" its looking odd and not readable too.

So Typescript config file have answer for the same. Just specify the baseUrl, config will take care of your relative path.

way to config: tsconfig.json file add the below properties.

"baseUrl": "src",
    "paths": {
      "@app/*": [ "app/*" ],
      "@env/*": [ "environments/*" ]
    }

So Finally it will look like below

import { Something } from "@app/src/[browser/server/universal]/...";

Its looks simple,awesome and more readable..

Solution 9 - Typescript

if typescript + webpack 2 + at-loader is being used, there is an additional step (@mleko's solution was only partially working for me):

// tsconfig.json
{
  "compilerOptions": {
    ...
    "rootDir": ".",
    "paths": {
      "lib/*": [
        "src/org/global/lib/*"
      ]
    }
  }
}    

// webpack.config.js
const { TsConfigPathsPlugin } = require('awesome-typescript-loader');

resolve: {
    plugins: [
        new TsConfigPathsPlugin(/* { tsconfig, compiler } */)
    ]
}

Advanced path resolution in TypeScript 2.0

Solution 10 - Typescript

Solution for 2021.

Note: CRA. Initially the idea of ​​using a third party library or ejecting app for alias seemed crazy to me. However, after 8 hours of searching (and trying variant with eject), it turned out that this option is the least painful.

Step 1.

yarn add --dev react-app-rewired react-app-rewire-alias

Step 2. Create config-overrides.js file in your project's root and fill it with :

const {alias} = require('react-app-rewire-alias')

module.exports = function override(config) {
  return alias({
    assets: './src/assets',
    '@components': './src/components',
  })(config)
}

Step 3. Fix your package.json file:

  "scripts": {
-   "start": "react-scripts start",
+   "start": "react-app-rewired start",
-   "build": "react-scripts build",
+   "build": "react-app-rewired build",
-   "test": "react-scripts test",
+   "test": "react-app-rewired test",
    "eject": "react-scripts eject"
}

If @declarations don't work, add them to the d.ts file. For example: '@constants': './src/constants', => add in react-app-env.d.ts declare module '@constants';

That is all. Now you can continue to use yarn or npm start/build/test commands as usual.

Full version in docs.

Note: The 'Using with ts / js config' part in docs did not work for me. The error "aliased imports are not supported" when building the project remained. So I used an easier way. Luckily it works.

Solution 11 - Typescript

{
  "compilerOptions": {
    "baseUrl": "src"
  },
  "include": ["src"]
}

i'm not sure if we must define the paths. but after write baseUrl to src i can import all folder under src folder like this

import { Home } from "pages";
import { formatDate } from "utils";
import { Navbar } from "components";

don't forget to restart your terminal after change the tsconfig.json

Solution 12 - Typescript

If you are looking for the most minimalist example for referencing your root folder with @, this would be it:

{
  "compilerOptions": {
    "baseUrl": "src",
    "paths": {
      "@/*": ["*"]
    }
  }
}
// Example usage: import * as logUtils from '@/utils/logUtils';

Or if you don't even have a src folder or would like to explicitly include it in the imports, this would also work:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["*"]
    }
  }
}
// Example usage: import * as logUtils from '@/src/utils/logUtils';

Solution 13 - Typescript

It looks like there has been an update to React that doesn't allow you to set the "paths" in the tsconfig.json anylonger.

Nicely React just outputs a warning:

The following changes are being made to your tsconfig.json file:
  - compilerOptions.paths must not be set (aliased imports are not supported)

then updates your tsconfig.json and removes the entire "paths" section for you. There is a way to get around this run

npm run eject

This will eject all of the create-react-scripts settings by adding config and scripts directories and build/config files into your project. This also allows a lot more control over how everything is built, named etc. by updating the {project}/config/* files.

Then update your tsconfig.json

{
    "compilerOptions": {
        "baseUrl": "./src",
        {}
        "paths": {
            "assets/*": [ "assets/*" ],
            "styles/*": [ "styles/*" ]
        }
    },
}

Solution 14 - Typescript

Checkout the compiler operation using this

I have added baseUrl in the file for a project like below :

"baseUrl": "src"

It is working fine. So add your base directory for your project.

Solution 15 - Typescript

/ starts from the root only, to get the relative path we should use ./ or ../

Solution 16 - Typescript

You can do this with just Node by using Subpath patterns.

For example, adding this to your package.json...

{
    "imports": {
        "#lib": "./build/path/to/lib",
        "#lib/*": "./build/path/to/lib/*",
    }
}

...will let you import like so, avoiding relative paths.

import { something } from "#lib"

Note that they must start with a hash, and in package.json, they must point to your build so Node can recognize it.

Like others have said, you can add something like this to your tsconfig.json for Typescript:

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "#lib": ["./src/path/to/lib"],
            "#lib/*": ["./src/path/to/lib/*"],
        },
    },
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRemo H. JansenView Question on Stackoverflow
Solution 1 - TypescriptAlejandro LoraView Answer on Stackoverflow
Solution 2 - TypescriptmlekoView Answer on Stackoverflow
Solution 3 - TypescriptAgBorkowskiView Answer on Stackoverflow
Solution 4 - TypescriptJoonView Answer on Stackoverflow
Solution 5 - TypescriptFacePalmView Answer on Stackoverflow
Solution 6 - TypescriptJames MoranView Answer on Stackoverflow
Solution 7 - TypescriptktretyakView Answer on Stackoverflow
Solution 8 - TypescriptVijayView Answer on Stackoverflow
Solution 9 - TypescripteeglbalazsView Answer on Stackoverflow
Solution 10 - TypescriptMadaShindeInaiView Answer on Stackoverflow
Solution 11 - TypescriptZacquioView Answer on Stackoverflow
Solution 12 - TypescriptcprcrackView Answer on Stackoverflow
Solution 13 - TypescriptAndy BrahamView Answer on Stackoverflow
Solution 14 - Typescriptdivya_kanakView Answer on Stackoverflow
Solution 15 - TypescriptVipindas GopalanView Answer on Stackoverflow
Solution 16 - Typescripthf02View Answer on Stackoverflow