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

32.8k views Asked by At

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

6

There are 6 answers

0
morpet On

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

0
Omar Omeiri On

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": {}
      }
    }
}
3
Angelo P On

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.

4
Abraham On

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"
3
Jamal On

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/*"]
        }
    }
}


1
windmaomao On

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.