Using eslint with typescript - Unable to resolve path to module
Asked Answered
T

23

368

I have this import in my file app.spec.ts:

import app from './app';

Which causes this Typescript error

2:17  error  Unable to resolve path to module './app'  import/no-unresolved

./app.ts does exist, but I have not compiled the .ts file into a .js file. As soon as I compile the .ts file to a .js, the error goes away.

However, since eslint is supposed to work with typescript, it should resolve modules with the .ts and not the .js.

I've also added the typescript information in my eslint config file:

"parser": "@typescript-eslint/parser",
"parserOptions": {
    "project": "./tsconfig.json"
}

How can I config eslint in such a way that it tries to resolve modules with the .ts and not the .js?

EDIT #1

Content of app.ts:

import bodyParser from 'body-parser';
import express from 'express';
import graphqlHTTP from 'express-graphql';
import { buildSchema } from 'graphql';

const app = express();

const schema = buildSchema(`
    type Query {
        hello: String
    }
`);
const root = { hello: () => 'Hello world!' };

app.use(bodyParser());
app.use('/graphql', graphqlHTTP({
    schema,
    rootValue: root,
    graphiql: true,
}));

export default app;
Trimly answered 16/3, 2019 at 15:35 Comment(8)
Have you added "plugins": ["@typescript-eslint"]? Docs github.com/typescript-eslint/typescript-eslint/tree/master/…Onus
Hey @Jasmonate, thanks for the answer! So I just added this config, and while I can now do some Typescript-specific linting, it does not solve my problem. I still get Unable to resolve path to module './app'Coelostat
Have you tried adding this into your .eslintrc? settings: { 'import/resolver': 'webpack' } (I'm assuming the code builds OK. If not, you will need to tell webpack to resolve .ts/.tsx files as well, which means adding something like: ``` module.exports = { resolve: { extensions: ['.js', '.ts'] } }; ``` or whatever file extensions you want to be able to import! )Cantatrice
The above comment is incomplete, I'm afraid! I ran out of editing time having pressed enter too soon! The module.exports = { resolve: { extensions: ['.js', '.ts'] } }; bit should be in your webpack config!Cantatrice
Can you add the content of your app.ts file ?Conscientious
Hey @Abulafia! Unfortunately, I am not using webpack...Coelostat
@Eastrall I edited the question with the content of app.ts :)Coelostat
If all else fails, you can try deleting node_modules, reinstalling, and restarting TS serverInoperable
C
622

You can set the ESLint module import resolution by adding this snippet to your .eslintrc.json configuration file:

{
  "settings": {
    "import/resolver": {
      "node": {
        "extensions": [".js", ".jsx", ".ts", ".tsx"]
      }
    }
  },
  ...
}

More informations about resolvers: https://github.com/benmosher/eslint-plugin-import#resolvers.

Conscientious answered 21/3, 2019 at 12:51 Comment(7)
I believe the other answer is the right solution for this.Unsaid
This seemed to solve the Unable to resolve path to module error, but now I'm still getting a bunch of Missing file extension "tsx" for [...]Anent
Ahh, 'import/extensions': 0, helped: #56065109Anent
It's one of those days! I had this problem, used this solution, and it didn't work. Tried it again several hours later and then it works. Weird!Steeple
In my eslintrc.js config file, the "import/resolver" object needed to sit within the "rules" node, not the "settings" node as described above.Ebb
I needed to install: npm install eslint-import-resolver-alias --save-devInterphone
How do you do this with Flat Config?Ofris
A
236

I had the same problem and I was only able to fix it by adding the typescript plugin to .eslintrc, using the extends option in .eslintrc

  extends: [
    "plugin:import/errors",
    "plugin:import/warnings",
    "plugin:import/typescript",
  ],
Agueweed answered 21/6, 2019 at 3:28 Comment(8)
Thanks! Adding "plugin:import/typescript" is what fixed it for me.Milburt
Note that you need to 1. place "plugin:import/typescript" after "airbnb-base". 2. Remember to add "import" in plugins section.Fresnel
now i get Missing file extension "ts" for <file>Helicoid
^ fixed with: https://mcmap.net/q/93503/-typescript-eslint-missing-file-extension-quot-ts-quot-import-extensionsHelicoid
For some reason by just having "plugin:import/typescript", did not solved this problem for me. The solution was to use this: github.com/alexgorbatchev/eslint-import-resolver-typescriptLeer
If anyone tries this and gets the error Failed to load config plugin:import/typescript, make sure you're not on an ancient version of eslint-plugin-import like I was. The typescript config was added somewhere between 2.14.0 and 2.25.2.Achondrite
I think this is the best answer!Virginia
Notably the issue I had with this seems to be when I have those first two, the errors and warnings, they are still getting used, and since they are non-typescript, introduce the error. The typescript flavor correctly resolves the pathing based on my tsconfig. Now I am concerned about missing all the other vanilla lint rules. SighHelicon
R
147

This was the only solution that worked for me.

First, you need to install this package:

yarn add -D eslint-import-resolver-typescript

Then add this to your .eslintrc file so it can load the alias settings from your tsconfig.json into ESLint:

{
  "settings": {
    "import/resolver": {
      "typescript": {}
    },
  },
}
Race answered 17/8, 2020 at 12:41 Comment(10)
This is the only one that worked for me when using a monorepo and a path alias to a different package.Halt
@Semx11, Same here!Dorcy
it's only solution for me thx ;)Bitolj
` "typescript": {} ` did the trick for me.Anemophilous
Thanks for this solution, the other ones didn't really help in my use caseDeina
this worked for me, one thing to note is if you are using an IDE and the error is shown by the IDE, make sure that you check it with the command line, cause your IDE may be misconfigured.Column
Thanks! Missing eslint-import-resolver-typescript was the issue!Zig
this solved the path alias issue in a react-native cli projectAlkanet
this is what did the trick for me. I was missing this step. ThanksFelicitous
This was the only thing that worked for me. Thanks!Swetlana
L
119

This does it for me:

.eslintrc.js

{
    ...
    settings: {
        ...
        'import/resolver': {
            node: {
                extensions: ['.js', '.jsx', '.ts', '.tsx'],
                moduleDirectory: ['node_modules', 'src/'],
            },
        },
    }
}
Lapp answered 10/10, 2019 at 13:4 Comment(8)
This is what worked for me; even including the "plugin:import/*" extensions didn't do anything. The moduleDirectory line pointing to 'src/' was the key to get this working on my end.Rosinweed
This worked for me as well. Note that HAD to add the "moduleDirectory" key.Ringworm
Adding the moduleDirectory: ['node_modules', 'myModules/'] indeed helped. I've seen a partial version of this solution without 'moduleDirectory' property and it didn't work. This one did the trick.Invent
works after adding moduleDirectory: ['node_modules', 'src/']Siderosis
This worked for me using the same config in .eslintrc.json in the typescript react project.Isocline
This worked for me with Quasar v1 (quasar create <project> --branch v1) and airbnb-base ESLint config.Adessive
this works with nextjs, thanksWhalen
Add my voice to also say this is the only solution that also worked for me after trying pretty much everything else that I came across to solve this problemSaucepan
C
43

In my case I just had to change

import { SetOptional, SetRequired } from 'type-fest';

to

import type { SetOptional, SetRequired } from 'type-fest';
Cocainize answered 7/3, 2022 at 1:30 Comment(6)
@pedro_A you are the real MVP!Curlew
so much better than messing around with eslint/ts configs!Barhorst
Who would've thought. Can you explain why this solves the problem, or what exactly the problem was?Insulator
@Insulator Hello, unfortunately I don't know for sure hahaha... It feels like I wrote this answer years ago... The fact that this solution works makes me suspect it's a bug with typescript-eslint.Cocainize
It might have something to do with elision of type-only imports, somehow being done at the wrong time. Maybe the import resolver sees only an empty file (since everything was elided)? Or maybe it has something to do with modules whose typings use namespaces, such as type-fest, since the import type syntax interferes with those... (open the PR that introduced the syntax and search for "If the symbol is a namespace" there)Cocainize
I believe this is the proper solution here. type-fest might not have any real js and is just a ts declaration file, which causes eslint to complain.Fleecy
B
31

When using "eslint": "6.8.0" with "typescript": "3.8.3" besides adding the following to .eslintrc:

"settings": {
  "import/resolver": {
    "node": {
      "paths": ["src"],
      "extensions": [".js", ".jsx", ".ts", ".tsx"],
    }
  },
}

You also need to add this line to tsconfig.json under compilerOptions:

"compilerOptions": {
  ...
  // Base directory to resolve non-relative module names.
  "baseUrl": "src",
  ...
}
Build answered 6/4, 2020 at 17:24 Comment(3)
Greatly appreciated to add the baseUrl options, saved my dayStupa
In my case I had to add .d.ts to the list- the package csstypes only contains an index.d.ts: "settings": { "import/resolver": { "node": { "paths": [ "src" ], "extensions": [ ".js", ".jsx", ".d.ts", ".ts", ".tsx" ] } } }Contumacious
This can also solve the case when the eslint configuration is shared between several projects and therefore located in a top-level folder. Listing all projects' paths in the paths property solves the eslint error.Superintendency
F
25

If you've updated your .eslintrc and tsconfig.json files as suggested in the other answers, and you still have the problem - restart vscode.

Faceless answered 7/10, 2020 at 11:15 Comment(2)
That worked for me!! Thank you :)Ligetti
It didn't work for me.Inesinescapable
Y
13

for those who use babel-module just add the extensions so it would be something like this:

      "babel-module": {
        "extensions": [".js", ".jsx", ".ts", ".tsx"],
        "alias": {
          "app": "./app"
        }
      }
Yesterday answered 16/5, 2019 at 8:6 Comment(1)
Indeed. My "babel-module" had only {}Horeb
S
12

Both ts and eslint were barking at me, so I had to add the following to my .eslintrc file:

{ 
    ...
    "rules": {
        ....
        "import/extensions": "off"
    },
    "settings": {
        ....
        "import/resolver": {
            "node": {
                "extensions": [".js", ".jsx", ".ts", ".tsx"]
            }
        }
    }
}
Sanctify answered 13/3, 2020 at 18:53 Comment(2)
I needed both the "settings" and the "rules", as described in this answer. Thanks!Repress
barking!! Hats off👏🏻Interdigitate
T
7

First add "plugin:import/typescript" under extends like below :

"extends": [
    "airbnb-base",
    "plugin:import/typescript"
 ],

then below under rules

"rules": {
        "import/extensions": [
            "error",
            "ignorePackages",
            {
                "ts": "never"
            }
        ]
    }
Tiresome answered 15/12, 2020 at 13:13 Comment(0)
Z
7

When importing locale files for Angular (e.g. import localeEn from '@angular/common/locales/en';), I had to allow the .mjs extension.

Here is an excerpt of my .eslintrc.json:

  ...
  "extends": [
    ...
    "plugin:import/recommended",
    "plugin:import/typescript",
    ...
  ],
  "settings": {
    "import/resolver": {
      "node": {
        "extensions": [".ts", ".mjs"]
      }
    }
  },
  "rules": {
    ...
  }
  ...

Edit:

When importing HttpClient or HttpClientModule, the error came back. I found out that adding the .d.ts extension to the list fixed the issue, which also make more sense than the .mjs (that is no longer needed).

So here is my new .eslintrc.json:

  ...

  {
    "files": ["*.ts"],
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
      "project": ["tsconfig.json"],
      "createDefaultProgram": true
    },
    "settings": {
      "import/resolver": {
        "node": {
          "extensions": [".ts", ".d.ts"]
        }
      }
    },
    "extends": [
      "eslint:recommended",
      "plugin:import/recommended",
      "plugin:import/typescript",
      "plugin:@typescript-eslint/recommended",
      "plugin:@angular-eslint/recommended",
      "plugin:@angular-eslint/ng-cli-compat",
      "plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
      "plugin:@angular-eslint/template/process-inline-templates"
    ],
    "rules": {
      ...
    }
  }

  ...

(I'm using @angular-eslint, but you may have a different extends list)

Zippy answered 2/12, 2021 at 11:8 Comment(0)
R
6

In my case, ESLint wasn't able to resolve the types installed from DefinitelyTyped (@type/ packages), so I had to specify where to find them in .eslintrc like this:

"import/resolver": {
    "typescript": {},
    "node": {
        "extensions": [".js", ".ts"],
        "paths": ["node_modules/", "node_modules/@types"]
    }
},

I also added "typescript": {}, which is basically for using configs from tsconfig.json and I have eslint-import-resolver-typescript installed for it to work.

Ram answered 8/8, 2020 at 10:47 Comment(1)
alternatively, you can just tell it where your node modules are with 'node': { 'moduleDirectory': 'node_modules' }Rabato
C
5

My situation with ts monorepo was that I was not getting lint errors in IDE, all aliases were resolved alright, but as soon as I run eslint on one of the projects, I was getting

error  Unable to resolve path to module

It is important to show eslint path to each of your package's tsconfig file.

To sum up and for those with TS, aliases and monorepo:

  • install eslint-import-resolver-typescript
  • add to eslintrc.js settings (this will help ide and eslint to figure aliases and stuff):
    'import/resolver': {
      node: {
        paths: 'packages/*/src',
        extensions: ['.js', '.jsx', '.ts', '.tsx'],
      },
      typescript: {
        alwaysTryTypes: true,
        project:[
         path.resolve(__dirname, '.tsconfig.json'), // root tsconfig
         path.resolve(__dirname, './packages/projA/tsconfig.json'),
         path.resolve(__dirname, './packages/projB/tsconfig.json'),
         /* ...rest of projects path to its tsconfig */
        ],
      },
  • add to eslintrc.js extends:
{
 ...,
   'plugin:import/recommended',
   'plugin:import/typescript',
}

  • add to eslintrc.js plugins:
  plugins: ['@typescript-eslint', ..., 'import'],
  • add to eslintrc.js parserOptions (same as to settings) this will help eslint:
        project: [
          path.resolve(__dirname, '.tsconfig.json'), // root tsconfig
          path.resolve(__dirname, './packages/projA/tsconfig.json'),
          path.resolve(__dirname, './packages/projB/tsconfig.json'),
          /* ...rest of projects path to its tsconfig */
        ],
Coccus answered 13/2, 2022 at 10:39 Comment(1)
Nice! The path.resolve(__dirname, '.tsconfig.json') in project resolved it for me.Satchel
I
2

In case, if anyone needs to support child directory as well. For an example, it supports

  1. src/components/input => components/input
  2. src/api/external/request => external/request

    "settings": {
      "import/resolver": {
        "node": {
          "paths": ["src", "src/api"],
          "extensions": [".js", ".jsx", ".ts", ".tsx"]
        }
      }
    }
    

This is working example for eslint ^6.1.0

Interdigitate answered 24/2, 2020 at 15:11 Comment(0)
X
2

I had to add the typescript import to extends and then turn off the imports in the rules:

"extends": {
    "plugin:import/typescript"
},
"rules": {
    "import/extensions": "off"
}
Xerosis answered 21/4, 2020 at 17:12 Comment(1)
this doesn't solve the problem only it turn off the rulePouter
A
2

For me it was just simply installing eslint-import-resolver-node:

yarn add -D eslint-import-resolver-node
# or
npm install eslint-import-resolver-node --save-dev
Ablaut answered 26/9, 2021 at 15:56 Comment(0)
V
1

For me, this error was caused by using eslint-config-airbnb. It isn't set up to work properly with typescript. The best fix for that (from this answer) is to install eslint-config-airbnb-typescript. The npm page includes the setup instructions, which involves tweaking your eslint config to load it and pointing it at your typescript config.

Note that if you used create-react-app to set up your app, you'll have an eslintConfig block in package.json. You need to have one ESLint config. If you create an .eslintrc to set up typescript linting, you should delete the block from package.json and move any config from there into the one config file.

Vip answered 15/4, 2023 at 15:55 Comment(0)
A
1

The issue was that the paths were not correctly resolving for the source folder. To solve the problem, I added the father of the source folder to the paths as well.

Instead of:

"settings": {
  "import/resolver": {
    "node": {
      "extensions": [".js", ".jsx", ".ts", ".tsx"],
      "paths": ["src"]
    }
  }
}

I made the following modification:

"settings": {
  "import/resolver": {
    "node": {
      "extensions": [".js", ".jsx", ".ts", ".tsx"],
      "paths": ["src", "client/src"]
    }
  }
}

Explanation: By adding the "client/src" path, the resolver can now correctly locate the files within that directory when importing or resolving modules. This change resolved the path resolution issue I was facing in my project.

(Optional: If applicable, mention where the "settings" block should be placed in your project's configuration file, e.g., webpack.config.js, tsconfig.json, etc.)

I hope this solution helps others who encounter a similar problem!

Axiology answered 25/7, 2023 at 9:14 Comment(0)
A
1

In 2023 this helps me

  env: { browser: true, es2020: true, node: true },
  extends: [
    'plugin:react/recommended',
    'airbnb',
    'airbnb-typescript',
    'airbnb/hooks',
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:react-hooks/recommended',
    'plugin:import/recommended',
    'plugin:import/typescript',
    'prettier',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: './tsconfig.json',
    ecmaVersion: 2018,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
    // Airbnb disable eslint-import-resolver-typescript
    // See: https://github.com/iamturns/eslint-config-airbnb-typescript#why-is-importno-unresolved-disabled
    // But, To support the tsconfig baseUrl and paths for aliasese that we uses,
    // you need this package
    // See configuration here
    // https://github.com/alexgorbatchev/eslint-import-resolver-typescript#installation

    'import/parsers': {
      '@typescript-eslint/parser': ['.ts', '.tsx'],
    },
    'import/resolver': {
      typescript: {
        alwaysTryTypes: true,
      },
    },
Amick answered 31/8, 2023 at 0:24 Comment(0)
L
0

In my case, I had to delete the eslint cache, and then it worked like a charm. (Our yarn script is

"lint:eslint": "eslint . --cache --cache-location '../../eslintcache/' --format stylish"

.)

Landry answered 21/4, 2022 at 21:23 Comment(0)
S
0

I´ve spend a lot of hours trying several approaches from this page. But however this did not solve my problem. In my case I am using more then one tsconfig file in a large project.

I was adding eslint-import-resolver-typescript to my project:

npm install eslint-import-resolver-typescript

Afterwards I added this to my eslintrc:

    settings: {
        "import/resolver": {
            typescript: {
                project: ["./path/to/config.json", "./path/to/config2.json", "./path/to/config3.json"] // Pfad zu deiner tsconfig.json-Datei
            }
        }
    },
Secretarial answered 20/12, 2023 at 13:35 Comment(0)
K
0
  1. Add this to extends:

    "extends": [
      "airbnb-typescript",
    ]
    
  2. Add this to parserOptions:

    "parserOptions": {      
       "project": "./tsconfig.json"
     },
    
  3. Be sure to install the dev module:

    npm i --save-dev eslint-config-airbnb-typescript 
    
Kelseykelsi answered 6/2 at 15:1 Comment(1)
Thank you for your interest in contributing to the Stack Overflow community. This question already has quite a few answers—including one that has been extensively validated by the community. Are you certain your approach hasn’t been given previously? If so, it would be useful to explain how your approach is different, under what circumstances your approach might be preferred, and/or why you think the previous answers aren’t sufficient. Can you kindly edit your answer to offer an explanation?Bartolome
W
-19

Awesome people know how to solve this by oneliner in 2022:

"rules": {
  "import/extensions": [ "error", "ignorePackages", { "": "never" } ]
}
Waltman answered 26/3, 2022 at 14:46 Comment(3)
ignoring a problem and fixing a problem are very different solutions.Downandout
@ChunkyChunk: But the accepted one didn't work during my writing.Waltman
Nice title as well, nice job!Tamarah

© 2022 - 2024 — McMap. All rights reserved.