393

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;
8
  • 3
    Have you added "plugins": ["@typescript-eslint"]? Docs github.com/typescript-eslint/typescript-eslint/tree/master/… Commented Mar 16, 2019 at 15:53
  • 2
    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' Commented Mar 17, 2019 at 20:44
  • 1
    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! ) Commented Mar 21, 2019 at 12:02
  • 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! Commented Mar 21, 2019 at 12:09
  • Can you add the content of your app.ts file ? Commented Mar 21, 2019 at 12:22

26 Answers 26

645
+50

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.

Sign up to request clarification or add additional context in comments.

9 Comments

I believe the other answer is the right solution for this.
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 [...]
Ahh, 'import/extensions': 0, helped: stackoverflow.com/questions/56064609/…
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!
In my eslintrc.js config file, the "import/resolver" object needed to sit within the "rules" node, not the "settings" node as described above.
|
260

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",
  ],

8 Comments

Thanks! Adding "plugin:import/typescript" is what fixed it for me.
Note that you need to 1. place "plugin:import/typescript" after "airbnb-base". 2. Remember to add "import" in plugins section.
now i get Missing file extension "ts" for <file>
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-typescript
|
160

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": {}
    },
  },
}

10 Comments

This is the only one that worked for me when using a monorepo and a path alias to a different package.
@Semx11, Same here!
it's only solution for me thx ;)
` "typescript": {} ` did the trick for me.
Thanks for this solution, the other ones didn't really help in my use case
|
124

This does it for me:

.eslintrc.js

{
    ...
    settings: {
        ...
        'import/resolver': {
            node: {
                extensions: ['.js', '.jsx', '.ts', '.tsx', '.d.ts'],
                moduleDirectory: ['node_modules', 'src/'],
            },
        },
    }
}

9 Comments

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.
This worked for me as well. Note that HAD to add the "moduleDirectory" key.
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.
works after adding moduleDirectory: ['node_modules', 'src/']
This worked for me using the same config in .eslintrc.json in the typescript react project.
|
47

In my case I just had to change

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

to

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

6 Comments

@pedro_A you are the real MVP!
so much better than messing around with eslint/ts configs!
Who would've thought. Can you explain why this solves the problem, or what exactly the problem was?
@Bergi 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.
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)
|
32

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",
  ...
}

3 Comments

Greatly appreciated to add the baseUrl options, saved my day
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" ] } } }
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.
28

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

1 Comment

It didn't work for me.
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"
        }
      }

1 Comment

Indeed. My "babel-module" had only {}
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"]
            }
        }
    }
}

2 Comments

I needed both the "settings" and the "rules", as described in this answer. Thanks!
barking!! Hats off👏🏻
8

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)

Comments

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

Comments

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.

1 Comment

alternatively, you can just tell it where your node modules are with 'node': { 'moduleDirectory': 'node_modules' }
6

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 */
        ],

1 Comment

Nice! The path.resolve(__dirname, '.tsconfig.json') in project resolved it for me.
3

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"
}

2 Comments

this doesn't solve the problem only it turn off the rule
yes, this doesnt solve the problem, but is more than one static check needed? Won't TS fail to compile if it can't find the module? Feels like eslint is unnecesary in this case and that this answer kinda is the best one
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

Comments

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

Comments

2

This variant of .eslintrc.js configuration hepls me to solve this problem:

   settings: {
      'import/parsers': {
         '@typescript-eslint/parser': ['.ts', '.tsx'],
      },
      'import/resolver': {
         node: {
            extensions: ['.js', '.jsx', '.ts', '.tsx'],
         },
         typescript: {
            alwaysTryTypes: true, // always try to resolve types under `<root>@types` directory even it doesn't contain any source code, like `@types/unist`

            // use an array of glob patterns
            project: ['**/tsconfig.json'],
         },
      },
   }

Oh, and dont forget this:

npm i eslint-import-resolver-typescript

and see the docs - https://www.npmjs.com/package/eslint-import-resolver-typescript

1 Comment

I tried all the answers above but only this worked for me. Can anyone explain what this settings actually do?
2

If anybody uses ESLint 9, defineConfig, eslint-plugin-import-x & eslint-import-resolver-typescript, make sure you've enabled all configs:

import js from '@eslint/js';
import globals from 'globals';
import tseslint from 'typescript-eslint';
import { defineConfig } from 'eslint/config';
import { importX } from 'eslint-plugin-import-x';
// ...

export default defineConfig([
  tseslint.configs.recommended,
  {
    // ...
    files: ['**/*.{js,mjs,cjs,ts,mts,cts}'],
    plugins: {
      js,
      'import-x': importX,
      // ...
    },
    extends: [
      'js/recommended',
      'import-x/flat/recommended',
      'import-x/flat/typescript',  // <-- I mean this one
      // ...
    ],
    languageOptions: {
      ecmaVersion: 2020,
      globals: { ...globals.browser, ...globals.node },
      parserOptions: {
        ecmaVersion: 'latest',
        ecmaFeatures: { jsx: true },
        sourceType: 'module',
      },
    },
    rules: {
      // ...
    },
  },
  // ...
]);

Comments

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.

Comments

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!

Comments

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,
      },
    },

Comments

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"

.)

Comments

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
            }
        }
    },

Comments

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 
    

1 Comment

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?
0

Modify your ESLint configuration to ignore virtual paths by adding the following rule:

'import/no-unresolved': ['error', { ignore: ['^virtual:'] }]

Comments

-21

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

"rules": {
  "import/extensions": [ "error", "ignorePackages", { "": "never" } ]
}

3 Comments

ignoring a problem and fixing a problem are very different solutions.
@ChunkyChunk: But the accepted one didn't work during my writing.
Nice title as well, nice job!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.