compilerOptions.paths must not be set (alias imports are not supported)
Asked Answered
I

6

22

I'm trying to map paths in tsconfig.json to get rid of relative paths hell. My React App is based on Create-React-App. I tried this SO thread and added paths in my tsconfig.json. My tsconfig.json is as

{
  "compilerOptions": {
    "baseUrl": "src",
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react",
    "strictNullChecks": false
  },
  "include": [
    "src"
  ]
}

when I compile my project in VS Code, it removes the paths entry from tsconfig.json with the following message. Why alias imports are not supported in my react-scripts based React Project?

enter image description here

Ideal answered 2/10, 2020 at 14:5 Comment(7)
did you find any solution?Amalamalbena
No, not yet....Ideal
What's wrong with using relative paths?Mystical
If you ever use this feature in Angular, you won't ask this question :)Ideal
@Amalamalbena Here is an answer https://mcmap.net/q/577002/-compileroptions-paths-must-not-be-set-alias-imports-are-not-supportedLeister
Why React is so problematic, I am coming from Angular and trying to switch to React, have problems with almost everything, including simple ts import pathsElectrolyze
I can understand your pain.... Same here. I also have an Angular background but I think it's a tradeoff between flexibility and features. Angular has first class support for Typescript but it's not the case with React. Still I think you will enjoy React once go through this initial transition period :)Ideal
L
12

Path aliases are no longer supported

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

go to your jsconfig.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"
Leister answered 13/8, 2021 at 22:38 Comment(4)
Where does the information come from that Path aliases are no longer supported? I have not found anything spontaneously.Hedva
On React start up. - compilerOptions.paths must not be set (aliased imports are not supported) But there is a workaroundRandallrandan
Welp: Error: Your project's 'baseUrl' can only be set to 'src' or 'node_modules'. Create React App does not support other values at this time.Elysha
For some reason this is the only way to make it work, my guts feeling is that react-script has different versions.Toddtoddie
R
6

I made to Angelo P's answer work by changing the config-overrides.js to

const path = require('path');

module.exports = function override(config, env) {
  config.resolve = {
    ...config.resolve,
    alias: {
      ...config.resolve.alias,
      "@src": path.resolve(__dirname, 'src/'),
      "@api": path.resolve(__dirname, "src/API/"),
      "@assets": path.resolve(__dirname, "src/assets/"),
      "@components": path.resolve(__dirname, "src/components/"),
      "@containers": path.resolve(__dirname, "src/containers/"),
      "@css": path.resolve(__dirname, "src/css/"),
      "@customHooks": path.resolve(__dirname, "src/CustomHooks/"),
      "@helperFuncs": path.resolve(__dirname, "src/HelperFuncs/"),
      "@hoc": path.resolve(__dirname, "src/hoc/"),
      "@middlewares": path.resolve(__dirname, "src/middlewares/"),
      "@models": path.resolve(__dirname, "src/models/"),
      "@store": path.resolve(__dirname, "src/store/"),
      "@actions": path.resolve(__dirname, "src/store/actions"),
      "@reducers": path.resolve(__dirname, "src/store/reducers/"),
      "@sagas": path.resolve(__dirname, "src/store/sagas/"),
      "@typings": path.resolve(__dirname, "src/Typings/"),
      "@utils": path.resolve(__dirname, "src/utils/")
    },
    extensions: ['.ts', '.tsx', '.js', '.jsx', '.json', '.d.ts']
  };
  return config;
};

Works like a charm, but the only thing missing is VSCode autocompletion. React starts up with this warning:

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

So I'm assuming it removes the path field from the tsconfig.json and VSCode cannot pick up the aliases, so ESLint and TS give the following errors in VSCode, but everything works fine.

Unable to resolve path to module '@typings/...'.eslintimport/no-unresolved

Cannot find module '@typings/...' or its corresponding type declarations.ts(2307)

Anyone has a solution for this?

UPDATE

Managed to get it all working by making these changes:

tsconfig.paths.json

{
  "compilerOptions": {
    "paths": {
      "@src/*": ["./src/*"],
      "@api/*": ["./src/API/*"],
      "@assets/*": ["./src/assets/*"],
      "@components/*": ["./src/components/*"],
      "@containers/*": ["./src/containers/*"],
      "@css/*": ["./src/css/*"],
      "@customHooks/*": ["./src/CustomHooks/*"],
      "@helperFuncs/*": ["./src/HelperFuncs/*"],
      "@hoc/*": ["./src/hoc/*"],
      "@middlewares/*": ["./src/middlewares/*"],
      "@models/*": ["./src/models/*"],
      "@store/*": ["./src/store/*"],
      "@actions/*": ["./src/store/actions*"],
      "@reducers/*": ["./src/store/reducers/*"],
      "@sagas/*": ["./src/store/sagas/*"],
      "@typings/*": ["./src/Typings/*"],
      "@utils/*": ["./src/utils/*"]
    }
  }
}

Note the * at the end of @.../*

tsconfig.json

{
  "extends": "./tsconfig.paths.json",
  "compilerOptions": {
    "target": "es6",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext",
      "es2015.promise"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "plugins": [
      {
        "name": "typescript-plugin-css-modules"
      }
    ],
    "resolveJsonModule": true,
    "baseUrl": ".",
  },
  "include": [
    "src",
    "src/**/*.ts"
  ]
}

npm i -D eslint-plugin-import @typescript-eslint/parser eslint-import-resolver-typescript

.eslintrc.json

{
    ...,
    "settings": {
      "import/resolver": {
        "node": {
          "extensions": [".js", ".jsx", ".ts", ".tsx", ".d.ts"]
        },
        "typescript": {}
      }
    }
}
Randallrandan answered 27/9, 2021 at 13:11 Comment(0)
D
4

you've probably already figured this one out but here's a solution while we wait for a pull request that adds this to tsconfig Currently having the same issue with create-react-app react v 17.0.2,

I've had a similar issue with gatsby applications where you're not able to just set up alias imports without changing the web pack config

this thread has a good explanation on alias imports within cra without typescript, but it should lead to the same configuration at the end of the day.

you'd have to either eject(don't do this unless you have other issues you need to solve inside of your webpack config.) or use another package like CRACO or React-App-Rewired to configure your aliases through webpack.

This Stackoverflow answer is most likely what you're looking for.

install react-app-rewired then create config-overrides.js and place this code in there ->

//config-overrides.js
const { alias, configPaths } = require('react-app-rewire-alias');

module.exports = function override(config) {
  return alias(configPaths('./tsconfig.paths.json'))(config);
};

create your paths object inside of tsconfig.paths.json

//tsconfig.paths.json
{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@components": ["components"],
      "@styles": ["styles"],
      "@config": ["config"]
    }
  }
}

then extend these options inside of tsconfig (not inside compilerOptions)

//tsconfig.js

 "extends": "./tsconfig.paths.json"

finally, replace each react-scripts script in your package.json with react-app-rewired

//package.json
"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-app-rewired eject"
},

You should be all set to go after this. Hoping this helps anyone else who runs into this problem with create-react-app.

Dwan answered 11/7, 2021 at 0:36 Comment(3)
Funnily enough, after testing this for a while and finally posting this it broke for me, so if anyone tries this out please do let me know if it works for them.Dwan
Hey! this did work for me! But I had to change the config-overrides.js. Checkout my answer.Randallrandan
Oh sick, Thanks a ton 😎Dwan
T
4

In the end, i figured out this is not the issue of tsconfig. Instead different build system reads this file and operate a bit differently. For instance, a NextJS build does most of the stuff according to the doc, but a Create React App build actually does not follow this exactly. For instance, I can only make the following work.

  import Avatar from 'src/components/Avatar'
{
  "compilerOptions": {
    "baseUrl": ".",

But nothing else with react-scripts. I hope this helps a bit in this crazy world.

Toddtoddie answered 6/3, 2023 at 16:59 Comment(1)
And were you able to make the paths work only with react-scripts?Amylase
E
3

You have to add "baseUrl": ".", to you compiler options and than you can use the import src/your/path directly.

Engross answered 28/1, 2021 at 22:43 Comment(0)
Z
3

You don't need craco for fixing the problem like that anymore. I've solved this issue by moving the baseUrl to the main tsconfig.json file like below:

tsconfig:

{
    "extends": "./tsconfig.paths.json",
    "compilerOptions": {
        "baseUrl": "./src",
        "target": "es5",
        "lib": ["dom", "dom.iterable", "esnext"],
        "allowJs": true,
        "experimentalDecorators": true,
        "skipLibCheck": true,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "strict": false,
        "noImplicitAny": false,
        "forceConsistentCasingInFileNames": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "noEmit": true,
        "jsx": "react"
    },
    "include": ["src"]
}

tsconfig.path.json:

{
    "compilerOptions": {
        "paths": {
            "api/*": ["api/*"],
            "assets/*": ["assets/*"],
            "config/*": ["config/*"],
            "components/*": ["components/*"],
            "hooks/*": ["hooks/*"],
            "pages/*": ["pages/*"],
            "store/*": ["store/*"],
            "constant/*": ["constant/*"],
            "types/*": ["types/*"],
            "utils/*": ["utils/*"]
        }
    }
}


Zigrang answered 1/1, 2022 at 9:13 Comment(3)
This is the best solution. Works with react-scripts 5.0 and does not require any additional plugins (craco, react-app-rewired etc). Thank you!Turnover
This does not actually work... it still strips out the paths... Here is what it prints out as it gets build... "The following changes are being made to your tsconfig.json file: - compilerOptions.paths must not be set (aliased imports are not supported)"Undercoating
@codenamezero, please check the order and exact paths, for example, start the wildcard on the end of the path.Zigrang

© 2022 - 2024 — McMap. All rights reserved.