Krimson
Krimson

Reputation: 7664

eslint complains about typescript's path aliasing

I've set up path aliasing in typescript's .tsconfig so my imports look cleaner.

In my code when I try and import my interface like this

import { ApiResponse } from '@api';

eslint complains: Unable to resolve path to module '@api' However, intelisense in vscode seems fine. Its able to give code prediction and "Jump to declaration" which is a clue that my .tsconfig is set up correctly but eslint is somehow misconfigured.


Relevant files

In my tsconfig.json, I've set up path aliasing like so:

{
  "compilerOptions": {
    "moduleResolution": "node",               
    "baseUrl": "./src",                     
    "paths": {                              
      "@api": ["./types/api"]
    },
  }
}

My ./src/types/api.ts looks like this:

// 3rd party API response object
export interface ApiResponse {
  ....
}

Finally, my .eslintrc.json looks like this:

{
  "env": {
    "node": true
  },
  "globals": {
    "console": true
  },
  "plugins": ["@typescript-eslint", "prettier"],
  "parser": "@typescript-eslint/parser",
  "settings": {
    "import/extensions": [".js", ".ts"],
    "import/parsers": {
      "@typescript-eslint/parser": [".ts"]
    },
    "import/resolver": {
      "node": {
        "extensions": [".js", ".ts"]
      }
    }
  }
}


Any idea what I may be doing wrong?

Upvotes: 74

Views: 63312

Answers (5)

fservantdev
fservantdev

Reputation: 755

It seems that @typescript-eslint now support path aliases.

I used to have many "Unsafe argument of type any assigned to a parameter of type string" errors
when using types coming from path aliases (using tsconfig's paths option)
but it was due to a misconfiguration of my parserOptions.project option.

Here is my project tree & working configuration (if it can help):

.
├── e2e/
│   ├── .eslintrc.js
│   └── tsconfig.json
├── src/
│   ├── app/
│   └── libs/
├── .eslintrc.js
├── tsconfig.base.json
├── tsconfig.eslint.json
└── tsconfig.json
// tsconfig.json
{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    ...,
    "paths": {
      "@foo/angular/*": ["./src/libs/modules/*"],
      "@foo/test/*": ["./src/libs/test/*"],
      "@foo/utils/*": ["./src/libs/utils/*"]
    }
  },
  ...
}
// tsconfig.eslint.json
{
  "extends": "./tsconfig.json",
  "include": ["src/**/*.ts", "e2e/**/*.ts"]
}
// .eslintrc.js
var config = {
  root: true,
  ignorePatterns: ['projects/**/*'],
  overrides: [
    {
      files: ['*.ts'],
      excludedFiles: ['node_modules/**/*'],
      extends: [
        'eslint:recommended',
        'plugin:@typescript-eslint/recommended',
        'plugin:@typescript-eslint/stylistic',
        ...
      ],
      parserOptions: {
        project: ['tsconfig.eslint.json'],
      },
      rules: { ... },
    },
  ],
};
// e2e/tsconfig.json
{
  "extends": "../tsconfig.base.json",
  "compilerOptions": {
    ...,
    "paths": {
      "@foo/auth/*": ["./src/libs/modules/auth/*"],
      "@foo/utils/*": ["./src/libs/utils/*"],
      "@my-app/*": ["./src/app/modules/*"]
    }
  },
  "include": ["src/**/*.ts"]
}
// e2e/.eslintrc.js
var config = {
  ignorePatterns: ['!**/*'],
  extends: ['../.eslintrc.js', 'plugin:cypress/recommended'],
  parserOptions: {
    project: ['e2e/tsconfig.json'],
  },
  rules: { ... },
};

Thus I don't have to rely on an additional eslint-import-resolver-typescript lib
or its dependencies eslint-plugin-import / eslint-plugin-import-x, which may be problematic [1] [2].

Upvotes: 0

saisriram manchella
saisriram manchella

Reputation: 136

I have created react native project with typescript enabled using expo. I have followed the below steps to add path aliasing

folder structure:

folder structure

Steps:

  1. Add baseURL and custom paths in tsconfig.json under compilerOptions as follow:

    "compilerOptions": {
             "allowSyntheticDefaultImports": true,
             "jsx": "react-native",
             "lib": [
             "dom",
             "esnext"
             ],
             "moduleResolution": "node",
             "noEmit": true,
             "skipLibCheck": true,
             "resolveJsonModule": true,
             "strict": true,
             "baseUrl": ".",
             "paths": {
               "*": ["src/*"],
               "$utility/*": ["src/utility/*"], // if /* is not added eslint throwing error so should be added in name and path as well
               "$themes/*": ["./src/themes/*"],
               "$assets/*": ["./src/assets/*"]
             }
         }
    
  2. Add aliases in babel.config.js under 'module-resolver' as follow:

module.exports = function (api) {
    api.cache(true);
    return {
        presets: ["babel-preset-expo"],
        plugins: [
            [
                'module-resolver',
                {
                    root: ["./src"],
                    alias: {
                        "$utility": './src/utility',
                        "$themes": './src/themes',
                        "$assets": './src/assets',
                    },
                },
            ],
        ],
    };
};

  1. Install eslint-plugin-import & eslint-import-resolver-typescript using following command:
    npm i -D eslint-plugin-import eslint-import-resolver-typescript

  2. After installing packages add typescript under import/resolver as below in eslintrc file:

           "settings": {
             "import/core-modules": ["@expo/vector-icons"],
             "import/extensions": [".js", ".jsx", ".ts", ".tsx"],
             "import/parsers": {
               "@typescript-eslint/parser": [".ts", ".tsx"]
             },
             "import/resolver": {
               "typescript": {},
               "node": {
                 "extensions": [".js", ".jsx", ".ts", ".tsx"]
               }
             }
         }
    
  3. Refresh vscode using command + shift + p -> Reload window.

Note: Projects created using expo will have babel-plugin-module-resolver package installed by default so no need to install it again

Upvotes: 8

ToluMals
ToluMals

Reputation: 51

My project is an electron app set up using the electron forge webpack-typescript template, I also added React to the project. I fixed this issue by:

  • adding eslint-import-resolver-typescript as a dev dependency
  • updating .eslintrc.json to include:
"settings": {
    "import/resolver": {
      "typescript": {}
    }
}

Upvotes: 2

gxmad
gxmad

Reputation: 2220

I had this problem, and it was trickier since I am using a monorepo structure. resolved that by using eslint-import-resolver-typescript.

As explained in the doc, inside your eslint config, you add this configuration pointing to all your projects.

// inside .eslintrc

"settings": {
  "import/resolver": {
    "typescript": {
      // use an array
      "project": [
        "packages/module-a/tsconfig.json",
        "packages/module-b/tsconfig.json"
      ],
    }
  }
}

Upvotes: 29

Shaun Luttin
Shaun Luttin

Reputation: 141542

To support the tsconfig baseUrl and paths, you need the package eslint-import-resolver-typescript.

  1. Make sure to have the basics:
# install the basics
npm i -D @typescript-eslint/parser @typescript-eslint/eslint-plugin

# support tsconfig baseUrl and paths
npm i -D eslint-plugin-import eslint-import-resolver-typescript
  1. Then in the eslintrc, here in json:
{
  "settings": {
    "import/resolver": {
      "typescript": {}
    }
  },
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": "./tsconfig.json",
    "tsconfigRootDir": "./"
  },
  "plugins": [
    "@typescript-eslint",
    "import"
  ],
  "extends": [
    "plugin:@typescript-eslint/recommended",
    "plugin:@typescript-eslint/recommended-requiring-type-checking"
  ]
}

Upvotes: 129

Related Questions