Typed Linting
Editor ESLint reports become out-of-date after file changes
There is a known issue in at least VS Code with typed linting that files might have out-of-date lint errors after multiple updates to files on disk. The root cause is that ESLint doesn't provide a way for editors to know about cross-file dependencies, such as type information. This results in files receiving out-of-date type information when files they import from are changed.
You might see this as erroneous no-unsafe-*
rule complaints on any
or error typed
values.
Other rules may be more subtly incorrect.
For now, the workaround is to run the Restart ESLint Server command in VS Code (or an equivalent in other editors) when types get out of date.
See ESLint does not re-compute cross-file information on file changes (microsoft/vscode-eslint#1774) for more information.
How do I disable type-checked linting for a file?
Use ESLint's configuration objects with our disable-type-checked
config to disable type checking for a files
match that includes that file.
For example, to disable type-checked linting on all .js
files:
- Flat Config
- Legacy Config
import tseslint from 'typescript-eslint';
export default tseslint.config(
// ... the rest of your config ...
{
files: ['**/*.js'],
extends: [tseslint.configs.disableTypeChecked],
},
);
module.exports = {
// ... the rest of your config ...
overrides: [
{
extends: ['plugin:@typescript-eslint/disable-type-checked'],
files: ['./**/*.js'],
},
],
};
Alternatively to disable type checking for files manually, you can set parserOptions: { project: false }
to an override for the files you wish to exclude.
typescript-eslint thinks my variable is never nullish / is any
/ etc., but that is clearly not the case to me
Our type-aware rules almost always trust the type information provided by the TypeScript compiler. Therefore, an easy way to check if our rule is behaving correctly is to inspect the type of the variable in question, such as by hovering over it in your IDE.
If the IDE also shows that the type is never nullish / is any
, you need to fix the type. A very common case is with the no-unnecessary-condition
rule. Take this code for example:
let condition = false;
const f = () => (condition = true);
f();
if (condition) {
//^^^^^^^^^ Unnecessary conditional, value is always falsy.
}
You can see that the type of condition
is actually the literal type false
by hovering over it in your IDE. In this case, typescript-eslint cannot possible know better than TypeScript itself, so you need to fix the report by fixing the type, such as through an assertion (let condition = false as boolean
).
If the IDE provides different type information from typescript-eslint's report, then make sure that the TypeScript setup used for your IDE, typescript-eslint, and tsc
are the same: the same TypeScript version, the same type-checking compiler options, and the same files being included in the project. For example, if a type is declared in another file but that file is not included, the type will become any
, and cause our no-unsafe-*
rules to report.
Are TypeScript project references supported?
Yes, but only with parserOptions.projectService
.
See issue #2094 discussing project references for more details.
Project Service Issues
parserOptions.projectService
is the recommended parser option to enable typed linting as of typescript-eslint v8.
It enforces projects generate type information for typed linting from the same tsconfig.json
files used by editors such as VS Code.
I get errors telling me "... was not found by the project service. Consider either including it in the tsconfig.json or including it in allowDefaultProject"
These errors are caused by attempting to use the project service to lint a file not explicitly included in its nearest tsconfig.json
.
The project service will attempt to build type information for each file being linted using the nearest tsconfig.json
on disk to that file.
If that tsconfig.json
does not include the file, and the file isn't allowlisted in allowDefaultProject
, then the project service will throw this error.
For each file being reported:
- If you do not want to lint the file:
- Use one of the options ESLint offers to ignore files, such an
ignores
config key.
- Use one of the options ESLint offers to ignore files, such an
- If you do want to lint the file:
- If you do not want to lint the file with type-aware linting: disable type-checked linting for that file.
- If you do want to lint the file with type-aware linting:
- If possible, add the file to the closest
tsconfig.json
'sinclude
. For example, allowing.js
files:tsconfig.json"include": [
"src",
+ "*.js"
] - Otherwise, if you have a small number of "out of project" files, try setting
projectService.allowDefaultProject
. - If not, you can switch to
parserOptions.project
for more fine-grained control of projects.
- If possible, add the file to the closest
Note also:
- TSConfigs don't include
.js
files by default. EnablingallowJs
orcheckJs
is required to do so. - The project service only looks at
tsconfig.json
files. It does not look attsconfig.eslint.json
or other coincidentally-similarly-named files.
If these steps don't work for you, please file an issue on typescript-eslint's typescript-estree package telling us your use case and why you need more out-of-project files linted. Be sure to include a minimal reproduction we can work with to understand your use case!
I get errors telling me "Having many files run with the default project is known to cause performance issues and slow down linting."
These errors are caused by attempting to use the project service to lint too many files not explicitly included in a tsconfig.json
with its allowDefaultProject
option.
typescript-eslint allows up to 8 "out of project" files by default. Each file causes a new TypeScript "program" to be built for each file it includes, which incurs a performance overhead for each file.
For each file being reported:
- If you do not want to lint the file:
- Use one of the options ESLint offers to ignore files, such an
ignores
config key.
- Use one of the options ESLint offers to ignore files, such an
- If you do want to lint the file:
- If you do not want to lint the file with type-aware linting: disable type-checked linting for that file.
- If you do want to lint the file with type-aware linting:
- If possible, add the file to the closest
tsconfig.json
'sinclude
instead of adding it toallowDefaultProject
. For example, allowing.js
files:tsconfig.json"include": [
"src",
+ "*.js"
] - If not, you can switch to
parserOptions.project
for more fine-grained control of projects.
- If possible, add the file to the closest
I'd like to use TSConfigs other than tsconfig.json
s for project service type information
Only the TSConfig path used for "out of project" files in allowDefaultProject
can be customized.
Otherwise, only tsconfig.json
files on disk will be read.
For example, instead of:
tsconfig.json
s for building (and, coincidentally, type information in editors)- Separate TSConfig(s) like
tsconfig.eslint.json
for linting
Consider using:
tsconfig.json
s for linting (and, intentionally, the same type information in editors)- Separate TSConfig(s) like
tsconfig.build.json
for building
The project service uses the same underlying TypeScript logic as editors such as VS Code.
Using only tsconfig.json
for typed linting enforces that the types seen in your editor match what's used for linting.
Traditional Project Issues
I get errors telling me "ESLint was configured to run ... However, that TSConfig does not / none of those TSConfigs include this file"
These errors are caused by an ESLint config requesting type information be generated for a file that isn't included in the TypeScript configuration.
Fixing the Error
- If you do not want to lint the file:
- Use one of the options ESLint offers to ignore files, namely a
.eslintignore
file, orignorePatterns
config.
- Use one of the options ESLint offers to ignore files, namely a
- If you do want to lint the file:
- If you do not want to lint the file with type-aware linting:
- Use ESLint's configuration objects with our
disable-type-checked
config to disable type checking for just that type of file.
- Use ESLint's configuration objects with our
- If you do want to lint the file with type-aware linting:
- Check the
include
option of each of the TSConfigs that you provide toparserOptions.project
- you must ensure that all files match aninclude
glob, or else our tooling will not be able to find it.- If the file is a
.cjs
,.js
, or.mjs
file, make sureallowJs
is enabled.
- If the file is a
- If your file shouldn't be a part of one of your existing tsconfigs (for example, it is a script/tool local to the repo), then consider creating a new tsconfig (we advise calling it
tsconfig.eslint.json
) in your project root which lists this file in itsinclude
. For an example of this, you can check out the configuration we previously used in this repo:
- Check the
- If you do not want to lint the file with type-aware linting:
More Details
This error may appear from the combination of two things:
- The ESLint configuration for the source file specifies at least one TSConfig file in
parserOptions.project
- None of those TSConfig files includes the source file being linted
- Note that files with the same name and different extension may not be recognized by TypeScript: see
parserOptions.project
docs
- Note that files with the same name and different extension may not be recognized by TypeScript: see
When TSConfig files are specified for parsing a source file, @typescript-eslint/parser
will use the first TSConfig that is able to include that source file (per aka.ms/tsconfig#include) to generate type information.
However, if no specified TSConfig includes the source file, the parser won't be able to generate type information.
This error most commonly happens on config files or similar that are not included in their project TSConfig(s). For example, many projects have files like:
- An
.eslintrc.cjs
/eslint.config.mjs
withparserOptions.project: true
- A
tsconfig.json
withinclude: ["src"]
In that case, viewing the file in an IDE with the ESLint extension will show the error notice that the file couldn't be linted because it isn't included in tsconfig.json
.
See our docs on type aware linting for more information.
I get errors telling me "The file must be included in at least one of the projects provided"
You're using an outdated version of @typescript-eslint/parser
.
Update to the latest version to see a more informative version of this error message, explained above.