60

I am trying to setup Path alias in my project by adding these values to tsconfig.json:

  "compilerOptions": {
    "baseUrl": "src",
    "paths": {
      "@store/*": ["store/*"]
    },

And if I create an import, neither IntelliJ or VSCode bother me:

import { AppState } from '@store/index';

But when I compile the application I get this warning:

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

And it bombs saying it cannot find the reference:

TypeScript error in C:/xyz.tsx(2,26):
Cannot find module '/store'.  TS2307

Is there any workaround or it is not supported by create-react-app --typescript?

Raffaeu
  • 6,694
  • 13
  • 68
  • 110

9 Answers9

51

In my case ,i solved this issue using craco and craco-alias

  1. Install craco and craco-alias : npm install @craco/craco --save && npm i -D craco-alias

  2. Create tsconfig.paths.json in root directory

    {
        "compilerOptions": {
            "baseUrl": "./src",
            "paths": {
               "@components/*" : ["./components/*"]
             }
        }
    }
    
  3. Extend tsconfig.paths.json in tsconfig.json

    {
        "extends": "./tsconfig.paths.json",
        //default configs...
    } 
    
  4. Create craco.config.js in root direcory

      const CracoAlias = require("craco-alias");
    
      module.exports = {
         plugins: [
           {
              plugin: CracoAlias,
              options: {
                 source: "tsconfig",
                 // baseUrl SHOULD be specified
                 // plugin does not take it from tsconfig
                 baseUrl: "./src",
                 /* tsConfigPath should point to the file where "baseUrl" and "paths" 
                 are specified*/
                 tsConfigPath: "./tsconfig.paths.json"
              }
           }
        ]
      };
    
  5. in package.json swap "start": "react-scripts start" with "start": "craco start"

mukuljainx
  • 716
  • 1
  • 6
  • 16
  • And then you should be able to use e.g: `import Bla from '@components/Bla';`? Where I have created a file at `./components/Bla.tsx`. – Jon G Aug 13 '20 at 15:43
  • I turned your steps into a script: https://pastebin.com/KkPUjZBU with the addition of my above comment. Unfortunately it fails with `Can't resolve '@components/Bla'`. Did I make a mistake? – Jon G Aug 13 '20 at 17:25
  • did you create components dir in src directory? If not , you need change absolute path in configs `"baseUrl": "./src"` – Иван Яковлев Aug 13 '20 at 19:47
  • or 61 line `cat > components/Bla.tsx` change on `cat > src/components/Bla.tsx` – Иван Яковлев Aug 13 '20 at 19:49
  • 2
    Ah, got it, thanks. Yes, I am trying to have a components package outside of src. I will try editing `"baseUrl"`. – Jon G Aug 14 '20 at 09:58
  • Thank you! This worked very well. If this does not work for anyone, please triple check your baseUrl and paths. – Thijmen Nov 11 '21 at 09:30
  • Thank you, this works. Do you need to replace the other scripts, like `"build": "craco build"`, etc? – Finley Nov 24 '21 at 06:53
  • Only this answer's solution works for me in 2022 – Sherali Turdiyev Apr 07 '22 at 08:54
  • I'm trying to follow [Atomic Design by Brad Frost](https://bradfrost.com/blog/post/atomic-web-design/). To do that I was setting paths in `tsconfig.paths.json` and extending it in the `tsconfig.json`. But then too I was getting the Module not found error. Upon searching I came here and it seems the last piece of puzzle was `craco-alias` since I'm using craco in my React App. Thank you very much. – August May 10 '22 at 11:29
17

The alias solution for craco or rewired create-react-app is react-app-alias for systems as: craco, react-app-rewired, customize-cra

According docs of mentioned systems replace react-scripts in package.json and configure next:

react-app-rewired

// config-overrides.js
const {aliasWebpack, aliasJest} = require('react-app-alias')

const options = {} // default is empty for most cases

module.exports = aliasWebpack(options)
module.exports.jest = aliasJest(options)

craco

// craco.config.js
const {CracoAliasPlugin} = require('react-app-alias')

module.exports = {
  plugins: [
    {
      plugin: CracoAliasPlugin,
      options: {}
    }
  ]
}

all

Configure aliases in json like this:

// tsconfig.paths.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "example/*": ["example/src/*"],
      "@library/*": ["library/src/*"]
    }
  }
}

And add this file in extends section of main typescript config file:

// tsconfig.json
{
  "extends": "./tsconfig.paths.json",
  // ...
}
oklas
  • 7,935
  • 2
  • 26
  • 42
  • 1
    react-app-rewire-alias also requires you to modify the npm scripts in package.json. Here is my code example if anyone interested: https://github.com/GW-Web-Enterprise/ReactJS/commit/c15eb084596ea8c7c258529ba9117bc88f3071b8. This code example removes the baseUrl compiler option and still keeps back the relative import for files at the src/* root to prevent any confusion might have such as import routes from 'src/routes' instead of import routes from './routes'. Because 'src' might make you think there is an external NPM package named 'src' – Son Nguyen Feb 14 '21 at 07:05
  • It compiles but it does not resolve in vscode – Topsy Feb 15 '22 at 17:42
  • Seems *"Not resolve in vscode"* is not related to react-app-rewire-alias or creact-react-app etc. Check what is [(ts/js)config.json](https://stackoverflow.com/a/68782883/2969544) - may be something wrong with it or vscode options. – oklas Feb 16 '22 at 04:36
10

Edit - 20/3/20 - Above answer has a solution with a plugin.

Had the same problem. At the time of posting it is currently not supported as is.

This feature is still in development with the CRA team: https://github.com/facebook/create-react-app/pull/6116

If you edit the tsconfig CRA removes changes: https://github.com/facebook/create-react-app/issues/6269

There are some hacks in this thread: https://github.com/facebook/create-react-app/issues/5118 to get aliases working however require customization to the CRA setup which isn't suitable for my use case (using CRA as is).

Marcus
  • 1,880
  • 20
  • 27
10

Path aliases no longer work in tsconfig.json

you can do this instead, to directly import files relative to the src directory

go to your tsconfig.json file add base URL to be "."

"compilerOptions": {
    "baseUrl":".",
    ...

then you can directly import stuff from the src directory

import Myfile from "src/myfile.js"
Abraham
  • 12,140
  • 4
  • 56
  • 92
3

@oklas. I've resolved using the following in config-overrides.js which is the same as above. But Thanks a lot for sharing this answer:

const { alias, configPaths } = require("react-app-rewire-alias");

module.exports = function override(config) {
  alias({
    ...configPaths("base-tsconfig.json"),
  })(config);
  return config;
};
Jalal
  • 3,308
  • 4
  • 35
  • 43
Brad
  • 181
  • 1
  • 11
2

This is an old post, but i've found an extremly simple solution using only package.json features.

"dependencies": {
  "@yourAlias": "file:./path/to/your/folder"
}

It works both in node.js and webpack projects

Poyoman
  • 1,652
  • 1
  • 20
  • 28
  • 1
    At least it seems working :) – Qwertiy Oct 27 '21 at 03:03
  • 1
    Could you elaborate on how you did this? It does not seem to work for me! – Thijmen Nov 11 '21 at 08:12
  • @Thijmen from tests i did, this is working fine with node.js using require, and webpack using import. This is not working fine with node.js using import. Is this your case ? – Poyoman Nov 11 '21 at 11:59
  • I eventually managed to get it working as illustrated in the comment by @Иван Яковлев! – Thijmen Nov 11 '21 at 15:01
  • For cra with typescript, works togehter the `paths` option in `tsconfig`, tho those "packages" are also under `src`. – Michael B. Aug 20 '22 at 18:49
1

Another workaround is just naming a folder inside ./src @ and setting the baseURL in the tsconfig.json to src.

Imports will then have a leading @/ like import { MyComponent } from "@/components/MyComponent"; or import { TodoEndpoint } from "@/endpoints/TodoEndpoint";. Since there is no library named @ in NPM this will not lead to conflict with other node_modules imports.

tsconfig.json

{
  "compilerOptions": {
    ...
    "baseUrl": "src"
  }
}

folder structure

+src
| +@
| | + components
| | +-  MyComponent.tsx
| | + endpoints
| | +-  TodoEndpoint.ts
| index.tsx
0

In 2022 for those who works with the ejected TypeScript create-react-app you can set aliases via webpack in config/webpack.config.js with the following:

    // ... the other keys of webpack config;
    resolve: {
        alias: {
            // ... here set your aliases among ones the CRA sets itself
            // NB: __dirname will refer to ./config so you have to put '../src' to move up from ./config folder and set @src tp ./src, not ./config/src;
            '@src': path.join(__dirname, '../src')
            // Here set your other aliases if needed.
        }
    }

Then use the alias in your ts/tsx files like this:

import logo from '@src/assets/logo.svg';

Here is webpack resolve docs for basics.

Note, that the only alias CRA sets itself is src, so you can use import logo from 'src/assets/logo.svg'; with no changes to webpack config. If the alias works in non-ejected app you have to check yourself.

Valentine Shi
  • 6,604
  • 4
  • 46
  • 46
-1

Have also solved the solution using craco with ts-loader - described here: https://stackoverflow.com/a/63545611/10813908

The stated setup essentially allows CRA to be extended upon by overidding the build-in webpack config via craco and also allows CRA code to directly reference typescript files in the external/shared packages in your mono-repo.

Zeeshan
  • 1,187
  • 1
  • 9
  • 12