How can I use paths in tsconfig.json?
Asked Answered
K

20

401

I was reading about path-mapping in file 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 file 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 configuration? Or is the tsconfig.json file enough?

Kutaisi answered 7/4, 2017 at 15:20 Comment(2)
Have look at npmjs.com/package/tspathMercaptopurine
See here: medium.com/@webia1.github/…Pretty
T
583

This can be set up on your tsconfig.json file, as it is a TypeScript 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, takes your baseUrl as the base of the route you are pointing to and it's mandatory as described on the documentation.

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.

Reference: Module resolution

Triangle answered 10/4, 2017 at 18:6 Comment(16)
Just a comment that might help others... if you are working with node.js or some environment that doesn't use a module bundler like webpack you will additionally need the npmjs.com/package/module-alias moduleKutaisi
This works completely fine but there is a problem when enable declaration and import this npm module in another module. Intelisense breaks. Any idea on how to fix this issue?Ratepayer
@siva - me too. Did you get an answer for this issue?Gauhati
@Gauhati not exactly. We moved to relative paths instead of aliases. But I found few ts plugin which does it: github.com/zerkalica/zerollup/tree/master/packages/…Ratepayer
I cannot get this to work. I have a tsconfig.json file, and then inside my src I have a tsconfig.app.json file. I have tried adding these values to both, with and without "*" and slashes. I'm just using angular-cli. Is there anything special that has to be done, like for webpack? Thanks!Camacho
@Aphax yes. it's possible to map to a single file, I prepared an example here: github.com/ialex90/TypeScript-Node-Starter/commit/…Triangle
@Camacho You need to add it only once, add it to the global one tsconfig.jsonTriangle
note that jest-test don't use the tsconfig-paths - you need to define a moduleNameMapper: tsjest#414Hahnke
this causes issues if you're using Jest BTW as the paths arent resolveable. there's a way to use aliases with jest. But then if you're using node too, it becomes yawnsome to have alias definitions in 4 different places.Belding
what if the module specified in the paths has its own package.json and node_modules? during compilation node_modules are not included in the dist folderAppetite
This answer would be much better, if it would have a warning that this will not work out-of-the-box on nodejs. Without such a warning, nodejs user will inevitably run in the infamous issue that TypeScript will successfully handle the path aliases at compile time, but since it doesn't rewrite import paths, nodejs will fail importing at runtime.Amu
Why the hell does no one have the answers to ionic. I guess no one uses it .But I tried about a billion solution similar to this and it doesnt work. I am using ionic 6. everything is just way too outdatedClangor
in order for the paths to work with nodejs you need to pre-load tsconfig-paths/register and ts-node/register/transpile-only.Eileneeilis
im having a really strange issue. In my compiler it works fine on all the includes but as soon as I try and instantiate the class it cant find the module event though in vs code it finds it etc. Any ideas? #67282299Saiva
For me setting the noEmit option to true in the tsconfig.json solved the problem in a node.js environment.Pradeep
While it works for me perfectly with not nested imports, no matter wheter it is with @ and/or initial _, it does not woth nested paths like 'assets/icons' again no matter...Lagunas
D
45

You can use a combination of the baseUrl and paths documentation.

Assuming root is in the topmost src directory (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 a module resolution. For Webpack 2, this could look like:

// webpack.config.js
module.exports = {
    resolve: {
        ...
        modules: [
            ...
            './src/org/global'
        ]
    }
}
Digamma answered 8/4, 2017 at 7:1 Comment(1)
Just noticing @mleko, @alejandro-lora used baseUrl, you talk rootDir ... — what's the difference?Moresque
L
26

Check this similar solutions with asterisk

  "baseUrl": ".",
  "paths": {
    "*": [
      "node_modules/*",
      "src/types/*"
    ]
  },
Lodger answered 22/2, 2018 at 10:59 Comment(3)
I don't see what he did here. What does this do?Doublecheck
@PaulRazvanBerg for all imports (*) try to find them on node_modules and src/typesNatatorial
But this cannot resolve .css files.Liebman
U
19

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';
Ubiety answered 25/3, 2022 at 14:25 Comment(1)
this breaks imports, like for example I had a axios.ts file and I had import axios from 'axios'; and it was referencing itself and giving me "any" as a result for the type, so I changed the code to "@/*": ["./src/*"] and removed baseUrlPrurient
C
18

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'
Cephalometer answered 16/5, 2019 at 7:5 Comment(0)
C
13

If you are using paths, you will need to change back absolute paths to relative paths for it to work after compiling TypeScript code into plain JavaScript code 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 the package.json file.

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.

Cahn answered 8/10, 2018 at 9:36 Comment(2)
There is a third way: use Vercel's ncc tool, which compiles your TypeScript project to a single file.Doublecheck
Use tsc-alias insteadMeliorate
P
11

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....

Pancho answered 6/6, 2021 at 12:18 Comment(0)
D
8

Alejandro's 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.

Dutyfree answered 25/6, 2018 at 11:38 Comment(0)
A
7

It’s kind of a relative path. Instead of the below code

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

We can avoid the "../../../../../". It’s looking odd and is not readable either.

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

Way to configuew: In the 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]/...";

It looks simple, awesome and more readable...

Altorilievo answered 19/3, 2019 at 14:5 Comment(0)
R
6

Use:

{
  "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 folders under the 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.

Roxane answered 19/1, 2022 at 13:50 Comment(0)
V
4

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

Viperine answered 27/7, 2017 at 9:56 Comment(1)
Please don't use TsConfigPathsPlugin. It's not well-maintained. There are many open issues regarding webpack v5.Liebman
B
3

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

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/configuration 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 file:

{
    "compilerOptions": {
        "baseUrl": "./src",
        {…}
        "paths": {
            "assets/*": [ "assets/*" ],
            "styles/*": [ "styles/*" ]
        }
    },
}
Betteanne answered 7/5, 2019 at 18:9 Comment(1)
Another workaround for this would be to inherit those values from another file. In your tsconfig, place this param and path to the base file ``` { ... "extends": "./tsconfig.base.json", ... } ``` Then in the tsconfig.base.json you can place your paths config ``` { "compilerOptions": { "paths": { "": [""] } } } ``` The error will still show, but it wont delete your settings anymore. There's more info on why this is happening here github.com/facebook/create-react-app/issues/…Straiten
A
3

You can do this with just Node.js 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/*"],
        },
    },
}
Appendage answered 31/1, 2022 at 21:34 Comment(0)
S
3

For a component library

If you are working on a library that returns UI components (like react-bootstrap or Ant Design) then this should work for you.

"compilerOptions": {
        ....
        "rootDir": "src",
        "baseUrl": ".",
        "paths": {
            "src/*": ["src/*"],
            "components/*": ["src/components/*"],
        }
  },
Samuels answered 27/10, 2022 at 12:3 Comment(1)
Why emphasize the rootDir here?Liebman
B
2

Check out 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.

Broddie answered 28/1, 2020 at 6:57 Comment(0)
F
2

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 documentation.

Note: The Using with TypeScript / JavaScript configuration 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.

Fibril answered 11/1, 2021 at 18:50 Comment(2)
react-app-rewired package is lightly maintained so you shouldn't continue with this package you should use craco insteadSeaworthy
I tried installing craco today and noticed there were around 20 out of date dependencies, some with critical vulnerabilities.Bellhop
S
1

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

Silesia answered 31/10, 2018 at 5:21 Comment(1)
Not true. Many options allow for non-relative module imports.Diverse
D
0

baseUrl being correct is important.

import Home from '@app/features/Home';

src/features/Home.tsx

  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
      "@app/*": [
        "src/*"
      ],
    },
Dunnage answered 29/8, 2022 at 0:43 Comment(0)
P
0

Make sure you have:

{
    "compileOnSave": true,
    "compilerOptions": {
        "paths": {
            "@styles/*": ["assets/scss/*"]
        }
    },
}

That was causing me issues.

Pigtail answered 31/10, 2022 at 15:56 Comment(0)
C
0

For me, Visual Studio Code was not recognizing the path, but the project was building just fine. The issue was that I had the paths declaration in a second tsconfig.app.json file.

Moving the paths property from tsconfig.app.json into tsconfig.json fixed the issue.


Supposedly, this is because Visual Studio Code only checks the first tsconfig.json file found in the root directory of the project, although I haven't confirmed that for myself. Perhaps someone can provide a comment with more information.

Churchwoman answered 2/9, 2023 at 22:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.