You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* docs: add guide for building ESLint plugins
* Corrected languageOptions placement
* Corrected languageOptions placement a bit more
* nit on custom rules: four
* Notes from Josh
* yarn format --write
* One last string parser reference
* remove requiresTypeChecking
Copy file name to clipboardExpand all lines: docs/developers/Custom_Rules.mdx
+23-25Lines changed: 23 additions & 25 deletions
Original file line number
Diff line number
Diff line change
@@ -10,11 +10,12 @@ You should be familiar with [ESLint's developer guide](https://eslint.org/docs/d
10
10
:::
11
11
12
12
As long as you are using `@typescript-eslint/parser` as the `parser` in your ESLint configuration, custom ESLint rules generally work the same way for JavaScript and TypeScript code.
13
-
The main three changes to custom rules writing are:
13
+
The main four changes to custom rules writing are:
14
14
15
15
-[Utils Package](#utils-package): we recommend using `@typescript-eslint/utils` to create custom rules
16
16
-[AST Extensions](#ast-extensions): targeting TypeScript-specific syntax in your rule selectors
17
17
-[Typed Rules](#typed-rules): using the TypeScript type checker to inform rule logic
18
+
-[Testing](#testing): using `@typescript-eslint/rule-tester`'s `RuleTester` instead of ESLint core's
18
19
19
20
## Utils Package
20
21
@@ -305,7 +306,6 @@ This rule bans for-of looping over an enum by using the TypeScript type checker
const type =services.getTypeAtLocation(node.right);
320
320
321
-
// 3. Check the TS type using the TypeScript APIs
322
-
if (tsutils.isTypeFlagSet(type, ts.TypeFlags.EnumLike)) {
321
+
// 3. Check the TS type's backing symbol for being an enum
322
+
if (type.symbol.flags&ts.SymbolFlags.Enum) {
323
323
context.report({
324
324
messageId: 'loopOverEnum',
325
325
node: node.right,
@@ -348,11 +348,15 @@ Rules can retrieve their full backing TypeScript type checker with `services.pro
348
348
This can be necessary for TypeScript APIs not wrapped by the parser services.
349
349
:::
350
350
351
-
:::caution
352
-
We recommend against changing rule logic based solely on whether `services.program` exists.
351
+
### Conditional Type Information
352
+
353
+
We recommend _against_ changing rule logic based solely on whether `services.program` exists.
353
354
In our experience, users are generally surprised when rules behave differently with or without type information.
354
355
Additionally, if they misconfigure their ESLint config, they may not realize why the rule started behaving differently.
355
356
Consider either gating type checking behind an explicit option for the rule or creating two versions of the rule instead.
357
+
358
+
:::tip
359
+
Documentation generators such as [`eslint-doc-generator`](https://github.com/bmish/eslint-doc-generator) can automatically indicate in a rule's docs whether it needs type information.
356
360
:::
357
361
358
362
## Testing
@@ -364,15 +368,13 @@ Below is a quick-start guide. For more in-depth docs and examples [see the `@typ
364
368
365
369
### Testing Untyped Rules
366
370
367
-
For rules that don't need type information, passing just the `parser` will do:
371
+
For rules that don't need type information, no constructor parameters are necessary:
This page describes how to write your own custom ESLint plugins using typescript-eslint.
9
+
You should be familiar with [ESLint's plugins guide](https://eslint.org/docs/latest/extend/plugins) and [typescript-eslint Custom Rules](./Custom_Rules.mdx) before writing custom plugins.
10
+
:::
11
+
12
+
Custom plugins that support TypeScript code and typed linting look very similar to any other ESLint plugin.
13
+
Follow the same general steps as [ESLint's plugins guide > _Creating a plugin_](https://eslint.org/docs/latest/extend/plugins#creating-a-plugin) to set up your plugin.
14
+
The required differences are noted on this page.
15
+
16
+
:::tip
17
+
See [**`eslint-plugin-example-typed-linting`**](https://github.com/typescript-eslint/examples/tree/main/packages/eslint-plugin-example-typed-linting) for an example plugin that supports typed linting.
18
+
:::
19
+
20
+
## Package Dependencies
21
+
22
+
Your plugin should have the following `package.json` entries.
23
+
24
+
For all `@typescript-eslint` and `typescript-eslint` packages, keep them at the same semver versions.
25
+
As an example, you might set each of them to `^8.1.2` or `^7.12.0 || ^8.0.0`.
26
+
27
+
### `dependencies`
28
+
29
+
[`@typescript-eslint/utils`](../packages/Utils.mdx) is required for the [`RuleCreator` factory to create rules](#rulecreator-usage).
30
+
31
+
### `devDependencies`
32
+
33
+
[`@typescript-eslint/rule-tester`](../packages/Rule_Tester.mdx) is strongly recommended to be able to [test rules with our `RuleTester`](./Custom_Rules.mdx).
34
+
35
+
### `peerDependencies`
36
+
37
+
Include the following to enforce the version range allowed without making users' package managers install them:
38
+
39
+
-`@typescript-eslint/parser` and any other parsers users are expected to be using
40
+
-`eslint`
41
+
-`typescript`
42
+
43
+
Those are all packages consumers are expected to be using already.
44
+
45
+
## `RuleCreator` Usage
46
+
47
+
We recommend including at least the following three properties in your plugin's [`RuleCreator` extra rule docs types](./Custom_Rules.mdx#extra-rule-docs-types):
48
+
49
+
-`description: string`: a succinct description of what the rule does
50
+
-`recommended?: boolean`: whether the rule exists in your plugin's shared _"`recommended`"_ config
51
+
-`requiresTypeChecking?: boolean`: whether the rule will use type information, for documentation generators such as [`eslint-doc-generator`](https://github.com/bmish/eslint-doc-generator)
52
+
53
+
For example, from [`eslint-plugin-example-typed-linting`'s `utils.ts`](https://github.com/typescript-eslint/examples/blob/main/packages/eslint-plugin-example-typed-linting/src/utils.ts):
Most ESLint plugins export a _"`recommended`"_[ESLint shared config](https://eslint.org/docs/latest/extend/shareable-configs).
73
+
Many ESLint users assume enabling a plugin's `recommended` config is enough to enable all its relevant rules.
74
+
75
+
However, at the same time, not all users want to or are able to enabled typed linting.
76
+
If your plugin's rules heavily use type information, it might be difficult to enable those in a `recommended` config.
77
+
78
+
You have roughly two options:
79
+
80
+
- Have your plugin's `recommended` config require enabling type information
81
+
- Have a separate config with a name like `recommendedTypeChecked`
82
+
83
+
Either way, explicitly mention the strategy taken in your docs.
84
+
85
+
:::info
86
+
Per [_Custom Rules_ > _Conditional Type Information_](./Custom_Rules.mdx#conditional-type-information), we recommend not changing rule logic based on whether type information is available.
87
+
:::
88
+
89
+
:::tip
90
+
See [**`eslint-plugin-example-typed-linting`**](https://github.com/typescript-eslint/examples/tree/main/packages/eslint-plugin-example-typed-linting) for an example plugin that supports typed linting.
0 commit comments