How to Lint All Files With Typescript ESLint

ESLint | Typescript

The Problem

Typescript ESLint is a great tool for adding linting to a Typescript project. It allows ESLint to natively parse Typescript syntax while also providing an extensive set of Typescript-specific rules. Many of these rules are “type-aware”, meaning they utilise the type information found within your project’s Typescript configuration (e.g., tsconfig.json) to provide more powerful analysis.

However, when enabling these type-aware rules, you may start to encounter an issue where linting certain files results in an error, usually seen as:

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

This is almost certainly because your ESLint configuration has been instructed to lint a file that does not belong to the Typescript project. Two common examples of this would be unit test files, or configuration files (such as .eslintrc.js itself).

This article will look at an easy solution that avoids this problem and allows any files of your choosing to be linted. Similar advice is officially documented here, along with solutions that may be applicable in the scenario where you explicitly don’t want the problem files to be linted.

The Solution

We’ll demonstrate the solution by expanding upon one of the examples mentioned above. Let’s assume we have a project where we’ve enabled type-aware linting but still want our .eslintrc.js file to be linted. We’d have a tsconfig.json and an .eslintrc.js that look something like the following (most options omitted for brevity):

// tsconfig.json

{
  "compilerOptions": {
    "outDir": "dist"
  },
  "include": ["src/**/*.ts"]
}
// .eslintrc.js

module.exports = {
  parserOptions: {
    parser: '@typescript-eslint/parser',
    sourceType: 'module',
    tsconfigRootDir: __dirname,
    project: 'tsconfig.json',
  },
  plugins: ['@typescript-eslint/eslint-plugin'],
  extends: [
    'plugin:@typescript-eslint/recommended',
    'plugin:@typescript-eslint/recommended-requiring-type-checking',
  ],
  ignorePatterns: ['node_modules', 'dist'],
};

As you can see, our Typescript configuration instructs that the project should only include .ts files within src (does not include .eslintrc.js), while our ESLint configuration has been instructed to lint everything outside of node_modules and dist (does include .eslintrc.js). What happens when we try to run the linter? As you might have expected, we get the following 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.

So, how do we fix this? We’ll simply create a separate Typescript configuration file and ask ESLint to use that instead. We’ll ensure the new configuration is derived from the original, so that we still provide the correct type information without repeating ourselves. Only this time, we’ll override the include option to contain all the files we’re interested in linting.

Let’s see that in action. First, we’ll create a new tsconfig.eslint.json file:

// tsconfig.eslint.json

{
  "extends": "./tsconfig.json",
  "include": ["./**/*.*"]
}

Notice how we use extends to inherit from the base configuration, and use include to now contain all files in the root directory (note that you may want to restrict this pattern if you find ./**/*.* to be too broad).

Finally, we just have to update .eslintrc.js and point it to our new ESLint-specific Typescript configuration:

// .eslintrc.js

module.exports = {
  parserOptions: {
    ...,
    project: 'tsconfig.eslint.json'
  },
  ...
};

That’s it! Now when we run the linter, no errors should be thrown and .eslintrc.js should be linted. Note how tsconfig.json remains unchanged, and that the core Typescript project can continue to function as normal.