Skip to content

docs: emphasize performance tradeoffs of typed linting #10730

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 19 additions & 128 deletions docs/getting-started/Typed_Linting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ title: Linting with Type Information
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

Some typescript-eslint rules utilize the awesome power of TypeScript's type checking APIs to provide much deeper insights into your code.
To tap into TypeScript's additional powers, there are two small changes you need to make to your config file:
Some typescript-eslint rules utilize TypeScript's type checking APIs to provide much deeper insights into your code.
This requires TypeScript to analyze your entire project instead of just the file being linted.
As a result, these rules are slower than traditional lint rules but are much more powerful.

To enable typed linting, there are two small changes you need to make to your config file:

<Tabs groupId="eslint-config">
<TabItem value="Flat Config">
Expand Down Expand Up @@ -44,9 +47,9 @@ For CommonJS modules and/or older versions of Node.js, [use `__dirname` or an al

In more detail:

- `tseslint.configs.recommendedTypeChecked` is another [shared configuration](../users/Shared_Configurations.mdx) we provide. This one contains recommended rules that additionally require type information.
- `parserOptions.projectService: true` indicates to ask TypeScript's type checking service for each source file's type information (see [Parser#projectService](../packages/Parser.mdx#projectService)).
- `parserOptions.tsconfigRootDir` tells our parser the absolute path of your project's root directory (see [Parser#tsconfigRootDir](../packages/Parser.mdx#tsconfigrootdir)).
- `tseslint.configs.recommendedTypeChecked` is a [shared configuration](../users/Shared_Configurations.mdx). It contains recommended rules that additionally require type information.
- `parserOptions.projectService: true` indicates to ask TypeScript's type checking service for each source file's type information (see [Parser > Project Service](../packages/Parser.mdx#projectservice)).
- `parserOptions.tsconfigRootDir` tells our parser the absolute path of your project's root directory (see [Parser > tsconfigRootDir](../packages/Parser.mdx#tsconfigrootdir)).

</TabItem>
<TabItem value="Legacy Config">
Expand Down Expand Up @@ -78,9 +81,9 @@ module.exports = {

In more detail:

- `plugin:@typescript-eslint/recommended-type-checked` is another [shared configuration](../users/Shared_Configurations.mdx) we provide. This one contains recommended rules that additionally require type information.
- `parserOptions.projectService: true` indicates to ask TypeScript's type checking service for each source file's type information (see [Parser#projectService](../packages/Parser.mdx#projectService)).
- `parserOptions.tsconfigRootDir` tells our parser the absolute path of your project's root directory (see [Parser#tsconfigRootDir](../packages/Parser.mdx#tsconfigrootdir)).
- `plugin:@typescript-eslint/recommended-type-checked` is a [shared configuration](../users/Shared_Configurations.mdx). It contains recommended rules that additionally require type information.
- `parserOptions.projectService: true` indicates to ask TypeScript's type checking service for each source file's type information (see [Parser > `projectService`](../packages/Parser.mdx#projectService)).
- `parserOptions.tsconfigRootDir` tells our parser the absolute path of your project's root directory (see [Parser > `tsconfigRootDir`](../packages/Parser.mdx#tsconfigrootdir)).

</TabItem>
</Tabs>
Expand Down Expand Up @@ -141,125 +144,7 @@ module.exports = {

You can read more about the rules provided by typescript-eslint in our [rules docs](/rules) and [shared configurations docs](../users/Shared_Configurations.mdx).

## FAQs

### Can I customize the TSConfig used for typed linting?

Yes, but it's not recommended in most configurations.
`parserOptions.projectService` uses the same "project service" APIs used by editors such as VS Code to generate TypeScript's type information.
Using a different TSConfig runs the risk of providing different types for typed linting than what your editor or `tsc` see.

If you absolutely must, the `parserOptions.project` option can be used instead of `parserOptions.projectService` with either:

- `true`: to always use `tsconfig.json`s nearest to source files
- `string | string[]`: any number of glob paths to match TSConfig files relative to `parserOptions.tsconfigRootDir`, or the current working directory if that is not provided

For example, if you use a specific `tsconfig.eslint.json` for linting, you'd specify:

<Tabs groupId="eslint-config">
<TabItem value="Flat Config">

```js title="eslint.config.mjs"
export default tseslint.config({
// ...
languageOptions: {
parserOptions: {
project: './tsconfig.eslint.json',
tsconfigRootDir: import.meta.dirname,
},
},
// ...
});
```

</TabItem>
<TabItem value="Legacy Config">

```js title=".eslintrc.js"
module.exports = {
// ...
parserOptions: {
project: './tsconfig.eslint.json',
tsconfigRootDir: __dirname,
},
// ...
};
```

</TabItem>
</Tabs>

See [the `@typescript-eslint/parser` `project` docs for more details](../packages/Parser.mdx#project).

:::note
If your project is a multi-package monorepo, see [our docs on configuring a monorepo](../troubleshooting/typed-linting/Monorepos.mdx).
:::

### How can I disable type-aware linting for a subset of files?

You can combine ESLint's [overrides](https://eslint.org/docs/latest/use/configure/configuration-files#configuration-based-on-glob-patterns) config in conjunction with our [`disable-type-checked`](../users/Shared_Configurations.mdx#disable-type-checked) config to turn off type-aware linting on specific subsets of files.

<Tabs groupId="eslint-config">
<TabItem value="Flat Config">

```js title="eslint.config.mjs"
export default tseslint.config(
eslint.configs.recommended,
tseslint.configs.recommendedTypeChecked,
tseslint.configs.stylisticTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
// Added lines start
{
files: ['**/*.js'],
extends: [tseslint.configs.disableTypeChecked],
},
// Added lines end
);
```

</TabItem>
<TabItem value="Legacy Config">

```js title=".eslintrc.js"
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended-type-checked',
'plugin:@typescript-eslint/stylistic-type-checked',
],
plugins: ['@typescript-eslint'],
parser: '@typescript-eslint/parser',
parserOptions: {
projectService: true,
tsconfigRootDir: __dirname,
},
root: true,
// Added lines start
overrides: [
{
files: ['*.js'],
extends: ['plugin:@typescript-eslint/disable-type-checked'],
},
],
// Added lines end
};
```

</TabItem>
</Tabs>

:::info
If you use type-aware rules from other plugins, you will need to manually disable these rules or use a premade config they provide to disable them.
:::

### How is performance?
## Performance

Typed rules come with a catch.
By using typed linting in your config, you incur the performance penalty of asking TypeScript to do a build of your project before ESLint can do its linting.
Expand All @@ -270,7 +155,13 @@ Additionally, most users primarily consume lint errors via IDE plugins which, th
This means that generally they usually only run a complete lint before a push, or via their CI, where the extra time often doesn't matter.

**We strongly recommend you do use type-aware linting**, but the above information is included so that you can make your own, informed decision.
See [Troubleshooting > Typed Linting > Performance](../troubleshooting/typed-linting/Performance.mdx) for more information.

## Troubleshooting

If you're having problems getting this working, please have a look at our [Troubleshooting FAQs](../troubleshooting/faqs/General.mdx).
If you're having problems with typed linting, please see our [Troubleshooting FAQs](../troubleshooting/faqs/General.mdx) and in particular [Troubleshooting > Typed Linting](../troubleshooting/typed-linting/index.mdx).

For details on the parser options that enable typed linting, see:

- [Parser > `projectService`](../packages/Parser.mdx#projectService): our recommended option, with settings to customize TypeScript project information
- [Parser > `project`](../packages/Parser.mdx#projectService): an older option that can be used as an alternative
116 changes: 116 additions & 0 deletions docs/troubleshooting/typed-linting/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,70 @@ module.exports = {

Alternatively to disable type checking for files manually, you can set [`parserOptions: { project: false }`](../../packages/Parser.mdx#project) to an override for the files you wish to exclude.

## How can I disable type-aware linting for a set of files?

You can combine ESLint's [overrides](https://eslint.org/docs/latest/use/configure/configuration-files#configuration-based-on-glob-patterns) config in conjunction with our [`disable-type-checked`](../../users/Shared_Configurations.mdx#disable-type-checked) config to turn off type-aware linting on specific subsets of files.

<Tabs groupId="eslint-config">
<TabItem value="Flat Config">

```js title="eslint.config.mjs"
export default tseslint.config(
eslint.configs.recommended,
tseslint.configs.recommendedTypeChecked,
tseslint.configs.stylisticTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
// Added lines start
{
files: ['**/*.js'],
extends: [tseslint.configs.disableTypeChecked],
},
// Added lines end
);
```

</TabItem>
<TabItem value="Legacy Config">

```js title=".eslintrc.js"
module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended-type-checked',
'plugin:@typescript-eslint/stylistic-type-checked',
],
plugins: ['@typescript-eslint'],
parser: '@typescript-eslint/parser',
parserOptions: {
projectService: true,
tsconfigRootDir: __dirname,
},
root: true,
// Added lines start
overrides: [
{
files: ['*.js'],
extends: ['plugin:@typescript-eslint/disable-type-checked'],
},
],
// Added lines end
};
```

</TabItem>
</Tabs>

:::info
If you use type-aware rules from other plugins, you will need to manually disable these rules or use a premade config they provide to disable them.
:::

## 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.
Expand Down Expand Up @@ -215,3 +279,55 @@ See our docs on [type aware linting](../../getting-started/Typed_Linting.mdx) fo

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](#i-get-errors-telling-me-eslint-was-configured-to-run--however-that-tsconfig-does-not--none-of-those-tsconfigs-include-this-file 'backlink to I get errors telling me ESLint was configured to run ...').

### Can I customize the TSConfig used for the project?

Yes, but it's not recommended in most configurations.
`parserOptions.projectService` uses the same "project service" APIs used by editors such as VS Code to generate TypeScript's type information.
Using a different TSConfig runs the risk of providing different types for typed linting than what your editor or `tsc` see.

If you absolutely must, the `parserOptions.project` option can be used instead of `parserOptions.projectService` with either:

- `true`: to always use `tsconfig.json`s nearest to source files
- `string | string[]`: any number of glob paths to match TSConfig files relative to `parserOptions.tsconfigRootDir`, or the current working directory if that is not provided

For example, if you use a specific `tsconfig.eslint.json` for linting, you'd specify:

<Tabs groupId="eslint-config">
<TabItem value="Flat Config">

```js title="eslint.config.mjs"
export default tseslint.config({
// ...
languageOptions: {
parserOptions: {
project: './tsconfig.eslint.json',
tsconfigRootDir: import.meta.dirname,
},
},
// ...
});
```

</TabItem>
<TabItem value="Legacy Config">

```js title=".eslintrc.js"
module.exports = {
// ...
parserOptions: {
project: './tsconfig.eslint.json',
tsconfigRootDir: __dirname,
},
// ...
};
```

</TabItem>
</Tabs>

See [the `@typescript-eslint/parser` `project` docs for more details](../../packages/Parser.mdx#project).

:::note
If your project is a multi-package monorepo, see [Troubleshooting > Typed Linting > Monorepos](./Monorepos.mdx).
:::
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export function RuleAttributes({ name }: { name: string }): React.ReactNode {
<Link href="/getting-started/typed-linting" target="_blank">
type information
</Link>{' '}
to run.
to run, which comes with performance tradeoffs.
</>
),
emoji: '💭',
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy