18

ESLint seems to be unable to parse a ".eslintrc.js" file.

Steps to reproduce: I set up a new "hello world" TypeScript project as follows:

# Make a new directory for our new project
mkdir test
# Go into the new directory
cd test
# Create a "package.json" file
npm init --yes
# Install TypeScript
npm install typescript --save-dev
# Install ESLint (the linter)
npm install eslint --save-dev
# Install the Airbnb ESLint config (the most popular linting config in the world)
npm install eslint-config-airbnb-typescript --save-dev
# The import plugin for ESLint is needed for the Airbnb config to work properly with TypeScript
npm install eslint-plugin-import@^2.22.0 --save-dev
# The TypeScript plugin for ESLint is needed for the Airbnb config to work properly with TypeScript
npm install @typescript-eslint/eslint-plugin@^4.2.0 --save-dev
# Create the config file for TypeScript
touch tsconfig.json
# Create the config file for ESLint
touch .eslintrc.js
# Create the entry point for our TypeScript application
touch main.ts

I fill the "tsconfig.json" file with the following (a blank/default config):

{}

I fill the ".eslintrc.js" file with the following, as specified in the Airbnb documentation:

module.exports = {
  extends: ['airbnb-typescript/base'],
  parserOptions: {
    project: './tsconfig.json',
  },
};

I fill the "main.ts" with the following:

const foo = 'bar';

Then, when I run npx eslint main.ts, it correctly generates the following error:

  1:7  error  'foo' is assigned a value but never used  @typescript-eslint/no-unused-vars

Thus, ESLint appears to be working correctly. However, when I run npx eslint .eslintrc.js, I get the following error:

  0:0  error  Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: .eslintrc.js.
The file must be included in at least one of the projects provided

This error also appears in VSCode whenever I open the ".eslintrc.js" file. The error needs to be solved so that ESLint can lint the rest of the file. (To clarify, I want the ".eslintrc.js" file to be linted in the same way that I want my TypeScript source code to be linted - e.g. have 2 space indentation and so forth.)

Additional info: I am on Windows 10 LTSC with Node v14.8.0 and npm version 6.14.7.

James
  • 1,394
  • 2
  • 21
  • 31

2 Answers2

45

When you're using typescript-powered eslint rules (when your eslint config includes a "parserOptions.project" config), eslint throws an error if you attempt to lint a file that isn't one of the files that's included in the typescript project.

This is due to performance reasons - it used to be that eslint allowed this, but doing so would cause a a large performance hit, so they changed it to throw an error instead.

The solution to linting files that aren't part of your TS project is to create a tsconfig that extends your "real" tsconfig, but includes all the files you want to lint. This is usually called tsconfig.eslint.json and looks like this:

// Special typescript project file, used by eslint only.
{
    "extends": "./tsconfig.json",
    "include": [
        // repeated from base config's "include" setting
        "src",
        "tests",

        // these are the eslint-only inclusions
        ".eslintrc.js",
    ]
}

And in your .eslintrc.js you'll change project: './tsconfig.json' to project: './tsconfig.eslint.json'.

This should resolve the error and allow the .eslintrc.js file to be linted.

Retsam
  • 30,909
  • 11
  • 68
  • 90
  • 3
    Even after attempting to perform the steps above, I am still receiving the error. – cjones26 Mar 27 '21 at 21:03
  • why would we want to have that file linted by `typescript` if it is a `javascript` file? – SalahAdDin Aug 11 '21 at 22:17
  • @SalahAdDin It's not being 'linted by typescript', it's being linted by eslint with the `@eslint-typescript/parser`. But since it's using the typescript compiler to provide typings, it needs files to be included in the typescript project being used. – Retsam Aug 13 '21 at 02:01
  • Ok, but does not that parser parse the `javascript` file as `typescript` files? – SalahAdDin Aug 14 '21 at 12:24
  • @SalahAdDin Technically yes, but since the syntax of TS is a superset of the syntax of JS it doesn't matter. – Retsam Aug 18 '21 at 16:22
  • But it gives a lot of errores related to typing, for example. – SalahAdDin Aug 18 '21 at 21:07
  • @SalahAdDin It's possible some of the TS-only rules you have enabled don't work well when run against JS files, and you may need the overrides section to only enable them for TS files. But I usually don't run into this - the above configuration should work for most projects. – Retsam Aug 21 '21 at 22:48
  • Which section is that? – SalahAdDin Aug 25 '21 at 08:26
3

Retsam‘s answer works perfectly well. However, you could also only use @typescript-eslint/parser for TypeScript files by using ESLint’s overrides. This avoids having to create a new tsconfig.json just for ESLint.

module.exports = {
  // Common configuration for .eslintrc.js and TypeScript files
  rules: {
    eqeqeq: "error",
    "no-var": "error",
    // ...
  },
  overrides: [{
    files: "**/*.ts"
    // TypeScript-only configuration
    parser: "@typescript-eslint/parser",
    parserOptions: {
      project: "tsconfig.json",
      tsconfigRootDir: __dirname,
      sourceType: "module",
    },
    plugins: ["@typescript-eslint"],
    rules: {
      "@typescript-eslint/no-floating-promises": "error",
      // ...
    }
  ]},
}
Lauren Yim
  • 12,700
  • 2
  • 32
  • 59
  • 1
    Note that this approach only works with really simple ESLint configs. In my projects (and probably most projects), there are a lot of rules, and they are being inherited from a parent config like Airbnb or `eslint-plugin-typescript/recommended`. So it isn't feasible to split up N rules into "only JavaScript rules" and "only TypeScript" rules, because N is far too large. – James May 15 '22 at 20:34