From 1444c716d74c338dcfcab6c2bf43e90117a74c5f Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 28 Sep 2022 13:38:07 -0400 Subject: [PATCH 01/14] chore(eslint-plugin): enhance many rule descriptions --- ...4-enhancement-new-base-rule-extension.yaml | 5 ++- packages/eslint-plugin/docs/rules/README.md | 5 ++- .../rules/adjacent-overload-signatures.md | 8 ++-- .../eslint-plugin/docs/rules/array-type.md | 8 ++-- .../docs/rules/await-thenable.md | 7 +++- .../src/rules/adjacent-overload-signatures.ts | 2 +- .../eslint-plugin/src/rules/array-type.ts | 3 +- .../eslint-plugin/src/rules/comma-spacing.ts | 2 +- packages/website/sidebars/sidebar.rules.js | 4 +- packages/website/src/css/custom.css | 2 + .../theme/MDXComponents/RuleAttributes.tsx | 39 ++++++------------- 11 files changed, 38 insertions(+), 47 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/04-enhancement-new-base-rule-extension.yaml b/.github/ISSUE_TEMPLATE/04-enhancement-new-base-rule-extension.yaml index 1c02ebe658a4..ffe35dd058b5 100644 --- a/.github/ISSUE_TEMPLATE/04-enhancement-new-base-rule-extension.yaml +++ b/.github/ISSUE_TEMPLATE/04-enhancement-new-base-rule-extension.yaml @@ -11,8 +11,9 @@ body: attributes: value: | # What is a "Base Rule Extension"? - In some cases, ESLint provides a rule itself, but it doesn't support TypeScript syntax; either it crashes, or it ignores the syntax, or it falsely reports against it. - In these cases, we create what we call an extension rule; a rule within our plugin that has the same functionality, but also supports TypeScript. + In some cases, ESLint provides a rule itself, but it doesn't support TypeScript syntax. + It may crash, or it ignore the syntax, or falsely reports against it. + In these cases we create what we call an extension rule: a rule within our plugin that has the same functionality, but also supports TypeScript. - type: checkboxes id: sanity-checks attributes: diff --git a/packages/eslint-plugin/docs/rules/README.md b/packages/eslint-plugin/docs/rules/README.md index 7c6bd00d36df..937c5cab2692 100644 --- a/packages/eslint-plugin/docs/rules/README.md +++ b/packages/eslint-plugin/docs/rules/README.md @@ -17,7 +17,8 @@ import RulesTable from "@site/src/components/RulesTable"; ## Extension Rules -In some cases, ESLint provides a rule itself, but it doesn't support TypeScript syntax; either it crashes, or it ignores the syntax, or it falsely reports against it. -In these cases, we create what we call an extension rule; a rule within our plugin that has the same functionality, but also supports TypeScript. +In some cases, ESLint provides a rule itself, but it doesn't support TypeScript syntax. +It may crash, or it ignore the syntax, or falsely reports against it. +In these cases we create what we call an extension rule: a rule within our plugin that has the same functionality, but also supports TypeScript. diff --git a/packages/eslint-plugin/docs/rules/adjacent-overload-signatures.md b/packages/eslint-plugin/docs/rules/adjacent-overload-signatures.md index 422824d7f3e9..38e8fe6e05ac 100644 --- a/packages/eslint-plugin/docs/rules/adjacent-overload-signatures.md +++ b/packages/eslint-plugin/docs/rules/adjacent-overload-signatures.md @@ -1,17 +1,17 @@ --- -description: 'Require that member overloads be consecutive.' +description: 'Require that function overload signatures be consecutive.' --- > 🛑 This file is source code, not the primary documentation location! 🛑 > > See **https://typescript-eslint.io/rules/adjacent-overload-signatures** for documentation. -Grouping overloaded members together can improve readability of the code. +Function overload signatures represent multiple ways a function can be called, potentially with different return types. +It's typical for an interface or type alias describing a function to place all overload signatures next to each other. +If Signatures placed elsewhere in the type are easier to be missed by future developers reading the code. ## Rule Details -This rule aims to standardize the way overloaded members are organized. - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/array-type.md b/packages/eslint-plugin/docs/rules/array-type.md index 08b9ddfb3861..a0be02f0d63b 100644 --- a/packages/eslint-plugin/docs/rules/array-type.md +++ b/packages/eslint-plugin/docs/rules/array-type.md @@ -1,17 +1,17 @@ --- -description: 'Require using either `T[]` or `Array` for arrays.' +description: 'Require consistently using either `T[]` or `Array` for arrays.' --- > 🛑 This file is source code, not the primary documentation location! 🛑 > > See **https://typescript-eslint.io/rules/array-type** for documentation. -Using the same style for array definitions across your codebase makes it easier for your developers to read and understand the types. +TypeScript provides two equivalent ways to define an array type: `T[]` and `Array`. +The two styles are functionally equivalent. +Using the same style consistently across your codebase makes it easier for developers to read and understand array types. ## Rule Details -This rule aims to standardize usage of array types within your codebase. - ## Options The default config will enforce that all mutable and readonly arrays use the `'array'` syntax. diff --git a/packages/eslint-plugin/docs/rules/await-thenable.md b/packages/eslint-plugin/docs/rules/await-thenable.md index dda209099712..51c07d8652b7 100644 --- a/packages/eslint-plugin/docs/rules/await-thenable.md +++ b/packages/eslint-plugin/docs/rules/await-thenable.md @@ -6,8 +6,11 @@ description: 'Disallow awaiting a value that is not a Thenable.' > > See **https://typescript-eslint.io/rules/await-thenable** for documentation. -This rule disallows awaiting a value that is not a "Thenable" (an object which has `then` method, such as a Promise). -While it is valid JavaScript to await a non-`Promise`-like value (it will resolve immediately), this pattern is often a programmer error, such as forgetting to add parenthesis to call a function that returns a Promise. +A "Thenable" value is an object with has a `then` method, such as a Promise. +The `await` keyword is generally used to retrieve the result of calling a Thenable's `then` method. + +If the `await` keyword is used on a value that is not a Thenable, the value is directly resolved immediately. +While doing so is valid JavaScript, it i often a programmer error, such as forgetting to add parenthesis to call a function that returns a Promise. ## Rule Details diff --git a/packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts b/packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts index 7bf3b6ee052f..81877d08b398 100644 --- a/packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts +++ b/packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts @@ -19,7 +19,7 @@ export default util.createRule({ meta: { type: 'suggestion', docs: { - description: 'Require that member overloads be consecutive', + description: 'Require that function overload signatures be consecutive', recommended: 'error', }, schema: [], diff --git a/packages/eslint-plugin/src/rules/array-type.ts b/packages/eslint-plugin/src/rules/array-type.ts index d8d310f36233..92040d8106aa 100644 --- a/packages/eslint-plugin/src/rules/array-type.ts +++ b/packages/eslint-plugin/src/rules/array-type.ts @@ -90,7 +90,8 @@ export default util.createRule({ meta: { type: 'suggestion', docs: { - description: 'Require using either `T[]` or `Array` for arrays', + description: + 'Require consistently using either `T[]` or `Array` for arrays', recommended: 'strict', }, fixable: 'code', diff --git a/packages/eslint-plugin/src/rules/comma-spacing.ts b/packages/eslint-plugin/src/rules/comma-spacing.ts index 5538fffe4a51..fda50d1b2e4a 100644 --- a/packages/eslint-plugin/src/rules/comma-spacing.ts +++ b/packages/eslint-plugin/src/rules/comma-spacing.ts @@ -19,7 +19,7 @@ type MessageIds = 'unexpected' | 'missing'; export default createRule({ name: 'comma-spacing', meta: { - type: 'suggestion', + type: 'layout', docs: { description: 'Enforce consistent spacing before and after commas', recommended: false, diff --git a/packages/website/sidebars/sidebar.rules.js b/packages/website/sidebars/sidebar.rules.js index b50758724110..23a5bdcc1e05 100644 --- a/packages/website/sidebars/sidebar.rules.js +++ b/packages/website/sidebars/sidebar.rules.js @@ -13,9 +13,7 @@ const rules = Object.entries(plugin.rules).map(([name, rule]) => { const deprecatedRules = new Set(rules.filter(rule => rule.meta.deprecated)); const formattingRules = new Set( - rules.filter( - rule => !rule.meta.deprecated && rule.meta.fixable === 'whitespace', - ), + rules.filter(rule => !rule.meta.deprecated && rule.meta.type === 'layout'), ); const emphasizedRules = rules.filter( diff --git a/packages/website/src/css/custom.css b/packages/website/src/css/custom.css index 73d46606cb50..9c039bdc6f59 100644 --- a/packages/website/src/css/custom.css +++ b/packages/website/src/css/custom.css @@ -62,6 +62,8 @@ html[data-theme='dark']:root { --docsearch-muted-color: #aaa; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); + + --gray-border-shadow: var(--ifm-color-secondary-dark); } .header-github-link:hover { diff --git a/packages/website/src/theme/MDXComponents/RuleAttributes.tsx b/packages/website/src/theme/MDXComponents/RuleAttributes.tsx index 4248270628da..df10ffdc7cf0 100644 --- a/packages/website/src/theme/MDXComponents/RuleAttributes.tsx +++ b/packages/website/src/theme/MDXComponents/RuleAttributes.tsx @@ -4,42 +4,27 @@ import React from 'react'; import styles from './RuleAttributes.module.css'; +const recommendations = { + error: '✅ recommended', + warn: '✅ recommended', + strict: '🔒 Strict', + false: 'none', +}; + export function RuleAttributes({ name }: { name: string }): JSX.Element | null { const rules = useRulesMeta(); const rule = rules.find(rule => rule.name === name); - if (!rule) { + if (!rule?.docs) { return null; } + return ( <>

Attributes

  • - - Included in configs -
      -
    • - - ✅ Recommended -
    • -
    • - - 🔒 Strict -
    • -
    + + Included in config: {recommendations[`${rule.docs.recommended}`]}
  • 💭 Requires type information
  • From 2bdbb79628ed2c3090ba39c75e16e606c65a1223 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Wed, 28 Sep 2022 17:47:48 -0400 Subject: [PATCH 02/14] wip --- .../docs/rules/ban-ts-comment.md | 3 +- .../rules/class-literal-property-style.md | 6 +-- .../rules/consistent-generic-constructors.md | 1 + .../rules/consistent-indexed-object-style.md | 2 + .../docs/rules/consistent-type-assertions.md | 17 ++++++--- .../docs/rules/consistent-type-definitions.md | 5 ++- .../docs/rules/consistent-type-exports.md | 8 +--- .../docs/rules/consistent-type-imports.md | 7 +--- .../rules/explicit-function-return-type.md | 13 ++++--- .../rules/explicit-member-accessibility.md | 15 +++++--- .../rules/explicit-module-boundary-types.md | 4 +- .../docs/rules/member-delimiter-style.md | 20 ---------- .../docs/rules/member-ordering.md | 5 +-- .../docs/rules/method-signature-style.md | 12 +++--- .../src/rules/member-delimiter-style.ts | 4 +- packages/website/docusaurusConfig.ts | 2 +- packages/website/sidebars/sidebar.rules.js | 37 ++++++++++++++----- .../theme/MDXComponents/RuleAttributes.tsx | 1 - 18 files changed, 84 insertions(+), 78 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/ban-ts-comment.md b/packages/eslint-plugin/docs/rules/ban-ts-comment.md index efadc961e104..fa43afad4c76 100644 --- a/packages/eslint-plugin/docs/rules/ban-ts-comment.md +++ b/packages/eslint-plugin/docs/rules/ban-ts-comment.md @@ -7,7 +7,8 @@ description: 'Disallow `@ts-` comments or require descriptions after > See **https://typescript-eslint.io/rules/ban-ts-comment** for documentation. TypeScript provides several directive comments that can be used to alter how it processes files. -Using these to suppress TypeScript Compiler Errors reduces the effectiveness of TypeScript overall. +Using these to suppress TypeScript compiler errors reduces the effectiveness of TypeScript overall. +Instead, it's generally better to correct the types of code, to make directives unnecessary. The directive comments supported by TypeScript are: diff --git a/packages/eslint-plugin/docs/rules/class-literal-property-style.md b/packages/eslint-plugin/docs/rules/class-literal-property-style.md index 7d1acfcd4bb7..80c44b7f1291 100644 --- a/packages/eslint-plugin/docs/rules/class-literal-property-style.md +++ b/packages/eslint-plugin/docs/rules/class-literal-property-style.md @@ -7,13 +7,13 @@ description: 'Enforce that literals on classes are exposed in a consistent style > See **https://typescript-eslint.io/rules/class-literal-property-style** for documentation. When writing TypeScript applications, it's typically safe to store literal values on classes using fields with the `readonly` modifier to prevent them from being reassigned. -When writing TypeScript libraries that could be used by JavaScript users however, it's typically safer to expose these literals using `getter`s, since the `readonly` modifier is enforced at compile type. - -## Options +When writing TypeScript libraries that could be used by JavaScript users, however, it's typically safer to expose these literals using `getter`s, since the `readonly` modifier is enforced at compile type. This rule aims to ensure that literals exposed by classes are done so consistently, in one of the two style described above. By default this rule prefers the `fields` style as it means JS doesn't have to setup & teardown a function closure. +## Options + :::note This rule only checks for constant _literal_ values (string, template string, number, bigint, boolean, regexp, null). It does not check objects or arrays, because a readonly field behaves differently to a getter in those cases. It also does not check functions, as it is a common pattern to use readonly fields with arrow function values as auto-bound methods. diff --git a/packages/eslint-plugin/docs/rules/consistent-generic-constructors.md b/packages/eslint-plugin/docs/rules/consistent-generic-constructors.md index 893c4ce819e9..f7a31dcf4bf9 100644 --- a/packages/eslint-plugin/docs/rules/consistent-generic-constructors.md +++ b/packages/eslint-plugin/docs/rules/consistent-generic-constructors.md @@ -17,6 +17,7 @@ const map = new Map(); ``` This rule ensures that type arguments appear consistently on one side of the declaration. +Keeping to one side consistently improve code readability. ## Rule Details diff --git a/packages/eslint-plugin/docs/rules/consistent-indexed-object-style.md b/packages/eslint-plugin/docs/rules/consistent-indexed-object-style.md index 918c27fef618..45381a8bdf86 100644 --- a/packages/eslint-plugin/docs/rules/consistent-indexed-object-style.md +++ b/packages/eslint-plugin/docs/rules/consistent-indexed-object-style.md @@ -20,6 +20,8 @@ type Foo = { type Foo = Record; ``` +Keeping to one declaration form consistently improve code readability. + ## Rule Details This rule enforces a consistent way to define records. diff --git a/packages/eslint-plugin/docs/rules/consistent-type-assertions.md b/packages/eslint-plugin/docs/rules/consistent-type-assertions.md index f6d439613cba..4c7f87ee9558 100644 --- a/packages/eslint-plugin/docs/rules/consistent-type-assertions.md +++ b/packages/eslint-plugin/docs/rules/consistent-type-assertions.md @@ -6,15 +6,22 @@ description: 'Enforce consistent usage of type assertions.' > > See **https://typescript-eslint.io/rules/consistent-type-assertions** for documentation. -## Rule Details +TypeScript provides two syntaxes for "type assertions": -This rule aims to standardize the use of type assertion style across the codebase. +- Angle brackets: `value` +- As: `value as Type` -Type assertions are also commonly referred as "type casting" in TypeScript (even though it is technically slightly different to what is understood by type casting in other languages), so you can think of type assertions and type casting referring to the same thing. It is essentially you saying to the TypeScript compiler, "in this case, I know better than you!". +This rule aims to standardize the use of type assertion style across the codebase. +Keeping to one syntax consistently helps with code readability. -In addition to ensuring that type assertions are written in a consistent way, this rule also helps make your codebase more type-safe. +:::note +Type assertions are also commonly referred as "type casting" in TypeScript. +However, that term is technically slightly different to what is understood by type casting in other languages. +Type assertions are a way to say to the TypeScript compiler, _"I know better than you, it's actually this different type!"_. +::: -[`const` assertions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) are always allowed by this rule. Examples of them include `let x = "hello" as const;` and `let x = "hello";`. +[`const` assertions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) are always allowed by this rule. +Examples of them include `let x = "hello" as const;` and `let x = "hello";`. ## Options diff --git a/packages/eslint-plugin/docs/rules/consistent-type-definitions.md b/packages/eslint-plugin/docs/rules/consistent-type-definitions.md index 5d400a28a1c2..9d72abe36ae7 100644 --- a/packages/eslint-plugin/docs/rules/consistent-type-definitions.md +++ b/packages/eslint-plugin/docs/rules/consistent-type-definitions.md @@ -6,7 +6,7 @@ description: 'Enforce type definitions to consistently use either `interface` or > > See **https://typescript-eslint.io/rules/consistent-type-definitions** for documentation. -There are two ways to define a type. +TypeScript provides two common ways to define an object type: `interface` and `type`. ```ts // type alias @@ -22,6 +22,9 @@ interface T2 { } ``` +The two are generally very similar, and can often be used interchangeably. +Using the same type declaration style consistently helps with code readability. + ## Options - `"interface"` _(default)_: enforce using `interface`s for object type definitions. diff --git a/packages/eslint-plugin/docs/rules/consistent-type-exports.md b/packages/eslint-plugin/docs/rules/consistent-type-exports.md index 97a11e65a28f..2c9de243945d 100644 --- a/packages/eslint-plugin/docs/rules/consistent-type-exports.md +++ b/packages/eslint-plugin/docs/rules/consistent-type-exports.md @@ -6,15 +6,11 @@ description: 'Enforce consistent usage of type exports.' > > See **https://typescript-eslint.io/rules/consistent-type-exports** for documentation. -Type-only exports allow you to specify that 1 or more named exports are exported as type-only. This allows -transpilers to drop exports without knowing the types of the dependencies. +TypeScript allows specifying a `type` keyword on exports to indicate that the export exists only in the type system, not at runtime. +This allows transpilers to drop exports without knowing the types of the dependencies. ## Rule Details -This rule aims to standardize the use of type exports style. - -Given a class `Button`, and an interface `ButtonProps`, examples of code: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/consistent-type-imports.md b/packages/eslint-plugin/docs/rules/consistent-type-imports.md index 9293fca42c6a..6e6912d34cf2 100644 --- a/packages/eslint-plugin/docs/rules/consistent-type-imports.md +++ b/packages/eslint-plugin/docs/rules/consistent-type-imports.md @@ -6,11 +6,8 @@ description: 'Enforce consistent usage of type imports.' > > See **https://typescript-eslint.io/rules/consistent-type-imports** for documentation. -Type-only imports allow you to specify that an import can only be used in a type location, allowing certain optimizations within compilers. - -## Rule Details - -This rule aims to standardize the use of type imports style. +TypeScript allows specifying a `type` keyword on imports to indicate that the export exists only in the type system, not at runtime. +This allows transpilers to drop imports without knowing the types of the dependencies. ## Options diff --git a/packages/eslint-plugin/docs/rules/explicit-function-return-type.md b/packages/eslint-plugin/docs/rules/explicit-function-return-type.md index 5697be355b57..76a4d6a83f3b 100644 --- a/packages/eslint-plugin/docs/rules/explicit-function-return-type.md +++ b/packages/eslint-plugin/docs/rules/explicit-function-return-type.md @@ -6,14 +6,15 @@ description: 'Require explicit return types on functions and class methods.' > > See **https://typescript-eslint.io/rules/explicit-function-return-type** for documentation. -Explicit types for function return values makes it clear to any calling code what type is returned. -This ensures that the return value is assigned to a variable of the correct type; or in the case -where there is no return value, that the calling code doesn't try to use the undefined value when it -shouldn't. +Functions in TypeScript often don't need to be given an explicit return type annotation. +Leaving off the return type is less code to read or write and allows the compiler to infer it from the contents of the function. -## Rule Details +However, explicit return types do make it visually more clear what type is returned by a function. +They can also speed up TypeScript type checking performance in large codebases with many large functions. + +This rule enforces that functions do have an explicit return type annotation. -This rule aims to ensure that the values returned from functions are of the expected type. +## Rule Details diff --git a/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md b/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md index 6cb6068a8874..35d0a64a8b00 100644 --- a/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md +++ b/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md @@ -6,10 +6,13 @@ description: 'Require explicit accessibility modifiers on class properties and m > > See **https://typescript-eslint.io/rules/explicit-member-accessibility** for documentation. -Leaving off accessibility modifier and making everything public can make -your interface hard to use by others. -If you make all internal pieces private or protected, your interface will -be easier to use. +TypeScript allows placing explicit `public`, `protected`, and `private` accessibility modifiers in front of class members. +The modifiers exist solely in the type system and just server to describe who is allowed to access those members. + +Leaving off accessibility modifiers makes for less code to read and write. +Members are `public` by default. + +However, adding in explicit accessibility modifiers can be helpful in codebases with many classes for enforcing proper privacy of members. ## Rule Details @@ -18,7 +21,7 @@ which properties. ## Options -### Configuring in a mixed JS/TS codebase +### Configuring in a mixed JS/TS codebasez If you are working on a codebase within which you lint non-TypeScript code (i.e. `.js`/`.mjs`/`.cjs`/`.jsx`), you should ensure that you should use [ESLint `overrides`](https://eslint.org/docs/user-guide/configuring#disabling-rules-only-for-a-group-of-files) to only enable the rule on `.ts`/`.mts`/`.cts`/`.tsx` files. If you don't, then you will get unfixable lint errors reported within `.js`/`.mjs`/`.cjs`/`.jsx` files. @@ -324,4 +327,4 @@ If you think defaulting to public is a good default, then you should consider us ## Further Reading -- TypeScript [Accessibility Modifiers](https://www.typescriptlang.org/docs/handbook/classes.html#public-private-and-protected-modifiers) +- TypeScript [Accessibility Modifiers Handbook Docs](https://www.typescriptlang.org/docs/handbook/2/classes.html#member-visibility) diff --git a/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md b/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md index 48626a34b08f..ae5efb95c94f 100644 --- a/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md +++ b/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md @@ -7,11 +7,11 @@ description: "Require explicit return and argument types on exported functions' > See **https://typescript-eslint.io/rules/explicit-module-boundary-types** for documentation. Explicit types for function return values and arguments makes it clear to any calling code what is the module boundary's input and output. +Adding explicit type annotations for those types can help improve code readability. +It can also improve TypeScript type checking performance on larger codebases. ## Rule Details -This rule aims to ensure that the values returned from a module are of the expected type. - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/member-delimiter-style.md b/packages/eslint-plugin/docs/rules/member-delimiter-style.md index 1437e97ba600..c3fe53758d29 100644 --- a/packages/eslint-plugin/docs/rules/member-delimiter-style.md +++ b/packages/eslint-plugin/docs/rules/member-delimiter-style.md @@ -62,26 +62,6 @@ This rule aims to standardize the way interface and type literal members are del ## Options -```ts -interface BaseConfig { - multiline?: { - delimiter?: 'none' | 'semi' | 'comma'; - requireLast?: boolean; - }; - singleline?: { - delimiter?: 'semi' | 'comma'; - requireLast?: boolean; - }; -} -type Config = BaseConfig & { - overrides?: { - interface?: BaseConfig; - typeLiteral?: BaseConfig; - }; - multilineDetection?: 'brackets' | 'last-member'; -}; -``` - Default config: ```json diff --git a/packages/eslint-plugin/docs/rules/member-ordering.md b/packages/eslint-plugin/docs/rules/member-ordering.md index 2765aeb5dd6b..62d35a8a444e 100644 --- a/packages/eslint-plugin/docs/rules/member-ordering.md +++ b/packages/eslint-plugin/docs/rules/member-ordering.md @@ -6,11 +6,8 @@ description: 'Require a consistent member declaration order.' > > See **https://typescript-eslint.io/rules/member-ordering** for documentation. -A consistent ordering of fields, methods and constructors can make interfaces, type literals, classes and class expressions easier to read, navigate, and edit. - -## Rule Details - This rule aims to standardize the way class declarations, class expressions, interfaces and type literals are structured and ordered. +A consistent ordering of fields, methods and constructors can make interfaces, type literals, classes and class expressions easier to read, navigate, and edit. ## Options diff --git a/packages/eslint-plugin/docs/rules/method-signature-style.md b/packages/eslint-plugin/docs/rules/method-signature-style.md index 4d6bea7ebdfb..4997ea092811 100644 --- a/packages/eslint-plugin/docs/rules/method-signature-style.md +++ b/packages/eslint-plugin/docs/rules/method-signature-style.md @@ -6,20 +6,20 @@ description: 'Enforce using a particular method signature syntax.' > > See **https://typescript-eslint.io/rules/method-signature-style** for documentation. -There are two ways to define an object/interface function property. +TypeScript provides two ways to define an object/interface function property: ```ts -// method shorthand syntax -interface T1 { +interface Example { + // method shorthand syntax func(arg: string): number; -} -// regular property with function type -interface T2 { + // regular property with function type func: (arg: string) => number; } ``` +The two are very similar; most of the time it doesn't matter which one you use. + A good practice is to use the TypeScript's `strict` option (which implies `strictFunctionTypes`) which enables correct typechecking for function properties only (method signatures get old behavior). TypeScript FAQ: diff --git a/packages/eslint-plugin/src/rules/member-delimiter-style.ts b/packages/eslint-plugin/src/rules/member-delimiter-style.ts index 4ae205967ceb..53d2019e97d7 100644 --- a/packages/eslint-plugin/src/rules/member-delimiter-style.ts +++ b/packages/eslint-plugin/src/rules/member-delimiter-style.ts @@ -135,13 +135,13 @@ const makeFixFunction = ({ export default util.createRule({ name: 'member-delimiter-style', meta: { - type: 'suggestion', + type: 'layout', docs: { description: 'Require a specific member delimiter style for interfaces and type literals', recommended: false, }, - fixable: 'code', + fixable: 'whitespace', messages: { unexpectedComma: 'Unexpected separator (,).', unexpectedSemi: 'Unexpected separator (;).', diff --git a/packages/website/docusaurusConfig.ts b/packages/website/docusaurusConfig.ts index 1a9a41e548e0..4bc2a650ad90 100644 --- a/packages/website/docusaurusConfig.ts +++ b/packages/website/docusaurusConfig.ts @@ -141,7 +141,7 @@ const themeConfig: ThemeCommonConfig & AlgoliaThemeConfig = { }, ], // style: 'primary', - copyright: `Copyright © ${new Date().getFullYear()} TypeScript ESLint, Inc. Built with Docusaurus.`, + copyright: `Copyright © ${new Date().getFullYear()} TypeScript ESLint, Inc. Built with Docusaurus.`, }, prism: { theme: { diff --git a/packages/website/sidebars/sidebar.rules.js b/packages/website/sidebars/sidebar.rules.js index 23a5bdcc1e05..b5fd6ce147d5 100644 --- a/packages/website/sidebars/sidebar.rules.js +++ b/packages/website/sidebars/sidebar.rules.js @@ -16,9 +16,16 @@ const formattingRules = new Set( rules.filter(rule => !rule.meta.deprecated && rule.meta.type === 'layout'), ); -const emphasizedRules = rules.filter( +const extensionRules = new Set( + rules.filter( + rule => rule.meta.docs?.extendsBaseRule && !formattingRules.has(rule), + ), +); + +const typescriptRules = rules.filter( rule => !rule.meta.deprecated && + !extensionRules.has(rule) && !deprecatedRules.has(rule) && !formattingRules.has(rule), ); @@ -61,14 +68,26 @@ module.exports = { someSidebar: [ 'README', { - ...createCategory('Rules', emphasizedRules, [ - createCategory('Formatting Rules', Array.from(formattingRules)), - createCategory('Deprecated Rules', [ - ...Array.from(deprecatedRules), - ...paths, - ]), - ]), - collapsed: false, + ...createCategory( + 'Rules', + [], + [ + { + ...createCategory('TypeScript Rules', Array.from(typescriptRules)), + collapsed: false, + }, + { + ...createCategory('Extension Rules', Array.from(extensionRules)), + collapsed: false, + }, + createCategory('Formatting Rules', Array.from(formattingRules)), + createCategory('Deprecated Rules', [ + ...Array.from(deprecatedRules), + ...paths, + ]), + ], + ), + collapsible: false, }, ], }; diff --git a/packages/website/src/theme/MDXComponents/RuleAttributes.tsx b/packages/website/src/theme/MDXComponents/RuleAttributes.tsx index df10ffdc7cf0..1b1ea96278d6 100644 --- a/packages/website/src/theme/MDXComponents/RuleAttributes.tsx +++ b/packages/website/src/theme/MDXComponents/RuleAttributes.tsx @@ -1,5 +1,4 @@ import { useRulesMeta } from '@site/src/hooks/useRulesMeta'; -import type { TSESLint } from '@typescript-eslint/utils'; import React from 'react'; import styles from './RuleAttributes.module.css'; From b41274b842611a69dad4f082202b299fd264d872 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 30 Sep 2022 17:21:32 -0400 Subject: [PATCH 03/14] Progress --- packages/eslint-plugin/docs/rules/TEMPLATE.md | 2 +- .../rules/adjacent-overload-signatures.md | 2 +- .../eslint-plugin/docs/rules/array-type.md | 2 - .../docs/rules/await-thenable.md | 4 +- .../docs/rules/ban-ts-comment.md | 4 +- .../docs/rules/ban-tslint-comment.md | 4 +- .../eslint-plugin/docs/rules/ban-types.md | 4 +- .../eslint-plugin/docs/rules/brace-style.md | 2 +- .../rules/class-literal-property-style.md | 2 +- .../eslint-plugin/docs/rules/comma-dangle.md | 2 +- .../eslint-plugin/docs/rules/comma-spacing.md | 2 +- .../rules/consistent-generic-constructors.md | 5 +- .../rules/consistent-indexed-object-style.md | 4 - .../docs/rules/consistent-type-exports.md | 12 +- .../docs/rules/default-param-last.md | 2 +- .../eslint-plugin/docs/rules/dot-notation.md | 2 +- .../rules/explicit-function-return-type.md | 2 +- .../rules/explicit-member-accessibility.md | 3 +- .../rules/explicit-module-boundary-types.md | 2 +- .../docs/rules/func-call-spacing.md | 2 +- packages/eslint-plugin/docs/rules/indent.md | 2 +- .../docs/rules/init-declarations.md | 2 +- .../docs/rules/keyword-spacing.md | 2 +- .../docs/rules/lines-between-class-members.md | 2 +- .../docs/rules/member-delimiter-style.md | 2 +- .../docs/rules/member-ordering.md | 4 +- .../docs/rules/naming-convention.md | 4 +- .../docs/rules/no-array-constructor.md | 2 +- .../docs/rules/no-base-to-string.md | 16 +-- .../rules/no-confusing-non-null-assertion.md | 6 +- .../rules/no-confusing-void-expression.md | 9 +- .../docs/rules/no-dupe-class-members.md | 2 +- .../docs/rules/no-duplicate-enum-values.md | 7 +- .../docs/rules/no-dynamic-delete.md | 8 +- .../docs/rules/no-empty-function.md | 2 +- .../docs/rules/no-empty-interface.md | 8 +- .../docs/rules/no-explicit-any.md | 12 +- .../docs/rules/no-extra-non-null-assertion.md | 7 +- .../docs/rules/no-extra-parens.md | 2 +- .../eslint-plugin/docs/rules/no-extra-semi.md | 2 +- .../docs/rules/no-extraneous-class.md | 10 +- .../docs/rules/no-floating-promises.md | 4 +- .../docs/rules/no-for-in-array.md | 4 +- .../docs/rules/no-implicit-any-catch.md | 4 +- .../docs/rules/no-implied-eval.md | 4 +- .../docs/rules/no-inferrable-types.md | 2 +- .../docs/rules/no-invalid-this.md | 2 +- .../docs/rules/no-invalid-void-type.md | 4 +- .../eslint-plugin/docs/rules/no-loop-func.md | 2 +- .../docs/rules/no-loss-of-precision.md | 2 +- .../docs/rules/no-magic-numbers.md | 2 +- .../rules/no-meaningless-void-operator.md | 4 +- .../docs/rules/no-misused-new.md | 4 +- .../docs/rules/no-misused-promises.md | 2 +- .../eslint-plugin/docs/rules/no-namespace.md | 2 +- ...no-non-null-asserted-nullish-coalescing.md | 4 +- .../no-non-null-asserted-optional-chain.md | 4 +- .../docs/rules/no-non-null-assertion.md | 4 +- .../docs/rules/no-parameter-properties.md | 2 +- .../eslint-plugin/docs/rules/no-redeclare.md | 2 +- .../rules/no-redundant-type-constituents.md | 4 +- .../docs/rules/no-require-imports.md | 4 +- .../docs/rules/no-restricted-imports.md | 2 +- .../eslint-plugin/docs/rules/no-shadow.md | 2 +- .../eslint-plugin/docs/rules/no-this-alias.md | 2 +- .../docs/rules/no-throw-literal.md | 4 +- .../eslint-plugin/docs/rules/no-type-alias.md | 2 +- .../no-unnecessary-boolean-literal-compare.md | 4 +- .../docs/rules/no-unnecessary-condition.md | 4 +- .../docs/rules/no-unnecessary-qualifier.md | 4 +- .../rules/no-unnecessary-type-arguments.md | 4 +- .../rules/no-unnecessary-type-assertion.md | 4 +- .../rules/no-unnecessary-type-constraint.md | 4 +- .../docs/rules/no-unsafe-argument.md | 4 +- .../docs/rules/no-unsafe-assignment.md | 4 +- .../docs/rules/no-unsafe-call.md | 4 +- .../docs/rules/no-unsafe-member-access.md | 4 +- .../docs/rules/no-unsafe-return.md | 4 +- .../docs/rules/no-unused-expressions.md | 2 +- .../docs/rules/no-unused-vars.md | 2 +- .../docs/rules/no-use-before-define.md | 2 +- .../docs/rules/no-useless-constructor.md | 2 +- .../docs/rules/no-useless-empty-export.md | 4 +- .../docs/rules/no-var-requires.md | 4 +- .../non-nullable-type-assertion-style.md | 4 +- .../docs/rules/object-curly-spacing.md | 2 +- .../rules/padding-line-between-statements.md | 2 +- .../docs/rules/parameter-properties.md | 2 +- .../docs/rules/prefer-as-const.md | 4 +- .../docs/rules/prefer-enum-initializers.md | 4 +- .../eslint-plugin/docs/rules/prefer-for-of.md | 4 +- .../docs/rules/prefer-function-type.md | 4 +- .../docs/rules/prefer-includes.md | 4 +- .../docs/rules/prefer-literal-enum-member.md | 4 +- .../docs/rules/prefer-namespace-keyword.md | 2 +- .../docs/rules/prefer-nullish-coalescing.md | 2 +- .../docs/rules/prefer-optional-chain.md | 4 +- .../rules/prefer-readonly-parameter-types.md | 4 +- .../docs/rules/prefer-readonly.md | 4 +- .../rules/prefer-reduce-type-parameter.md | 4 +- .../docs/rules/prefer-regexp-exec.md | 4 +- .../docs/rules/prefer-return-this-type.md | 4 +- .../rules/prefer-string-starts-ends-with.md | 4 +- .../docs/rules/prefer-ts-expect-error.md | 4 +- .../docs/rules/promise-function-async.md | 2 +- packages/eslint-plugin/docs/rules/quotes.md | 2 +- .../docs/rules/require-array-sort-compare.md | 4 +- .../eslint-plugin/docs/rules/require-await.md | 2 +- .../docs/rules/restrict-plus-operands.md | 4 +- .../rules/restrict-template-expressions.md | 4 +- .../eslint-plugin/docs/rules/return-await.md | 2 +- packages/eslint-plugin/docs/rules/semi.md | 2 +- .../sort-type-union-intersection-members.md | 4 +- .../docs/rules/space-before-blocks.md | 2 +- .../docs/rules/space-before-function-paren.md | 2 +- .../docs/rules/strict-boolean-expressions.md | 2 - .../docs/rules/switch-exhaustiveness-check.md | 4 +- .../docs/rules/triple-slash-reference.md | 2 +- .../docs/rules/type-annotation-spacing.md | 2 +- packages/eslint-plugin/docs/rules/typedef.md | 2 +- .../docs/rules/unbound-method.md | 2 +- .../docs/rules/unified-signatures.md | 2 +- .../eslint-plugin/src/rules/ban-ts-comment.ts | 2 +- .../src/rules/no-extra-non-null-assertion.ts | 2 +- .../website/plugins/generated-rule-docs.ts | 2 +- packages/website/sidebars/sidebar.rules.js | 31 ++--- .../theme/MDXComponents/Feature.module.css | 23 ++++ .../src/theme/MDXComponents/Feature.tsx | 23 ++++ .../MDXComponents/RuleAttributes.module.css | 8 +- .../theme/MDXComponents/RuleAttributes.tsx | 121 ++++++++++++------ 130 files changed, 301 insertions(+), 340 deletions(-) create mode 100644 packages/website/src/theme/MDXComponents/Feature.module.css create mode 100644 packages/website/src/theme/MDXComponents/Feature.tsx diff --git a/packages/eslint-plugin/docs/rules/TEMPLATE.md b/packages/eslint-plugin/docs/rules/TEMPLATE.md index 20ca5d8bdbe6..ddc6def34a5c 100644 --- a/packages/eslint-plugin/docs/rules/TEMPLATE.md +++ b/packages/eslint-plugin/docs/rules/TEMPLATE.md @@ -2,7 +2,7 @@ > > See **https://typescript-eslint.io/rules/your-rule-name** for documentation. -## Rule Details +## Examples To fill out: tell us more about this rule. diff --git a/packages/eslint-plugin/docs/rules/adjacent-overload-signatures.md b/packages/eslint-plugin/docs/rules/adjacent-overload-signatures.md index 38e8fe6e05ac..b221b4497240 100644 --- a/packages/eslint-plugin/docs/rules/adjacent-overload-signatures.md +++ b/packages/eslint-plugin/docs/rules/adjacent-overload-signatures.md @@ -10,7 +10,7 @@ Function overload signatures represent multiple ways a function can be called, p It's typical for an interface or type alias describing a function to place all overload signatures next to each other. If Signatures placed elsewhere in the type are easier to be missed by future developers reading the code. -## Rule Details +## Examples diff --git a/packages/eslint-plugin/docs/rules/array-type.md b/packages/eslint-plugin/docs/rules/array-type.md index a0be02f0d63b..66905370cf02 100644 --- a/packages/eslint-plugin/docs/rules/array-type.md +++ b/packages/eslint-plugin/docs/rules/array-type.md @@ -10,8 +10,6 @@ TypeScript provides two equivalent ways to define an array type: `T[]` and `Arra The two styles are functionally equivalent. Using the same style consistently across your codebase makes it easier for developers to read and understand array types. -## Rule Details - ## Options The default config will enforce that all mutable and readonly arrays use the `'array'` syntax. diff --git a/packages/eslint-plugin/docs/rules/await-thenable.md b/packages/eslint-plugin/docs/rules/await-thenable.md index 51c07d8652b7..717f7e222008 100644 --- a/packages/eslint-plugin/docs/rules/await-thenable.md +++ b/packages/eslint-plugin/docs/rules/await-thenable.md @@ -12,9 +12,7 @@ The `await` keyword is generally used to retrieve the result of calling a Thenab If the `await` keyword is used on a value that is not a Thenable, the value is directly resolved immediately. While doing so is valid JavaScript, it i often a programmer error, such as forgetting to add parenthesis to call a function that returns a Promise. -## Rule Details - -Examples of code for this rule: +## Examples diff --git a/packages/eslint-plugin/docs/rules/ban-ts-comment.md b/packages/eslint-plugin/docs/rules/ban-ts-comment.md index fa43afad4c76..b0fa17f6aa07 100644 --- a/packages/eslint-plugin/docs/rules/ban-ts-comment.md +++ b/packages/eslint-plugin/docs/rules/ban-ts-comment.md @@ -1,5 +1,5 @@ --- -description: 'Disallow `@ts-` comments or require descriptions after directive.' +description: 'Disallow `@ts-` comments or require descriptions after directives.' --- > 🛑 This file is source code, not the primary documentation location! 🛑 @@ -19,8 +19,6 @@ The directive comments supported by TypeScript are: // @ts-check ``` -## Rule Details - This rule lets you set which directive comments you want to allow in your codebase. ## Options diff --git a/packages/eslint-plugin/docs/rules/ban-tslint-comment.md b/packages/eslint-plugin/docs/rules/ban-tslint-comment.md index fc9fe81af6bc..96a5e9b91dbc 100644 --- a/packages/eslint-plugin/docs/rules/ban-tslint-comment.md +++ b/packages/eslint-plugin/docs/rules/ban-tslint-comment.md @@ -8,9 +8,9 @@ description: 'Disallow `// tslint:` comments.' Useful when migrating from TSLint to ESLint. Once TSLint has been removed, this rule helps locate TSLint annotations (e.g. `// tslint:disable`). -## Rule Details +> See the [TSLint rule flags docs](https://palantir.github.io/tslint/usage/rule-flags) for reference. -All TSLint [rule flags](https://palantir.github.io/tslint/usage/rule-flags/) +## Examples diff --git a/packages/eslint-plugin/docs/rules/ban-types.md b/packages/eslint-plugin/docs/rules/ban-types.md index 2d0b345cda80..016b2a7217e7 100644 --- a/packages/eslint-plugin/docs/rules/ban-types.md +++ b/packages/eslint-plugin/docs/rules/ban-types.md @@ -9,11 +9,11 @@ description: 'Disallow certain types.' Some built-in types have aliases, while some types are considered dangerous or harmful. It's often a good idea to ban certain types to help with consistency and safety. -## Rule Details - This rule bans specific types and can suggest alternatives. Note that it does not ban the corresponding runtime objects from being used. +## Examples + Examples of code with the default options: diff --git a/packages/eslint-plugin/docs/rules/brace-style.md b/packages/eslint-plugin/docs/rules/brace-style.md index 18f93c48a5ed..4e032c80580d 100644 --- a/packages/eslint-plugin/docs/rules/brace-style.md +++ b/packages/eslint-plugin/docs/rules/brace-style.md @@ -6,7 +6,7 @@ description: 'Enforce consistent brace style for blocks.' > > See **https://typescript-eslint.io/rules/brace-style** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/brace-style`](https://eslint.org/docs/rules/brace-style) rule. It adds support for `enum`, `interface`, `namespace` and `module` declarations. diff --git a/packages/eslint-plugin/docs/rules/class-literal-property-style.md b/packages/eslint-plugin/docs/rules/class-literal-property-style.md index 80c44b7f1291..6ce4b454e5b5 100644 --- a/packages/eslint-plugin/docs/rules/class-literal-property-style.md +++ b/packages/eslint-plugin/docs/rules/class-literal-property-style.md @@ -6,7 +6,7 @@ description: 'Enforce that literals on classes are exposed in a consistent style > > See **https://typescript-eslint.io/rules/class-literal-property-style** for documentation. -When writing TypeScript applications, it's typically safe to store literal values on classes using fields with the `readonly` modifier to prevent them from being reassigned. +Some TypeScript applications store literal values on classes using fields with the `readonly` modifier to prevent them from being reassigned. When writing TypeScript libraries that could be used by JavaScript users, however, it's typically safer to expose these literals using `getter`s, since the `readonly` modifier is enforced at compile type. This rule aims to ensure that literals exposed by classes are done so consistently, in one of the two style described above. diff --git a/packages/eslint-plugin/docs/rules/comma-dangle.md b/packages/eslint-plugin/docs/rules/comma-dangle.md index 49f816448fbc..1f11f9cf3acf 100644 --- a/packages/eslint-plugin/docs/rules/comma-dangle.md +++ b/packages/eslint-plugin/docs/rules/comma-dangle.md @@ -6,7 +6,7 @@ description: 'Require or disallow trailing commas.' > > See **https://typescript-eslint.io/rules/comma-dangle** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/comma-dangle`](https://eslint.org/docs/rules/comma-dangle) rule. It adds support for TypeScript syntax. diff --git a/packages/eslint-plugin/docs/rules/comma-spacing.md b/packages/eslint-plugin/docs/rules/comma-spacing.md index af4959e146d6..9d5424811a85 100644 --- a/packages/eslint-plugin/docs/rules/comma-spacing.md +++ b/packages/eslint-plugin/docs/rules/comma-spacing.md @@ -6,7 +6,7 @@ description: 'Enforce consistent spacing before and after commas.' > > See **https://typescript-eslint.io/rules/comma-spacing** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/comma-spacing`](https://eslint.org/docs/rules/comma-spacing) rule. It adds support for trailing comma in a types parameters list. diff --git a/packages/eslint-plugin/docs/rules/consistent-generic-constructors.md b/packages/eslint-plugin/docs/rules/consistent-generic-constructors.md index f7a31dcf4bf9..6c259a70888f 100644 --- a/packages/eslint-plugin/docs/rules/consistent-generic-constructors.md +++ b/packages/eslint-plugin/docs/rules/consistent-generic-constructors.md @@ -19,9 +19,8 @@ const map = new Map(); This rule ensures that type arguments appear consistently on one side of the declaration. Keeping to one side consistently improve code readability. -## Rule Details - -The rule never reports when there are type parameters on both sides, or neither sides of the declaration. It also doesn't report if the names of the type annotation and the constructor don't match. +> The rule never reports when there are type parameters on both sides, or neither sides of the declaration. +> It also doesn't report if the names of the type annotation and the constructor don't match. ## Options diff --git a/packages/eslint-plugin/docs/rules/consistent-indexed-object-style.md b/packages/eslint-plugin/docs/rules/consistent-indexed-object-style.md index 45381a8bdf86..529d0719655a 100644 --- a/packages/eslint-plugin/docs/rules/consistent-indexed-object-style.md +++ b/packages/eslint-plugin/docs/rules/consistent-indexed-object-style.md @@ -22,10 +22,6 @@ type Foo = Record; Keeping to one declaration form consistently improve code readability. -## Rule Details - -This rule enforces a consistent way to define records. - ## Options - `"record"` _(default)_: only allow the `Record` type. diff --git a/packages/eslint-plugin/docs/rules/consistent-type-exports.md b/packages/eslint-plugin/docs/rules/consistent-type-exports.md index 2c9de243945d..ec15e9fdecb2 100644 --- a/packages/eslint-plugin/docs/rules/consistent-type-exports.md +++ b/packages/eslint-plugin/docs/rules/consistent-type-exports.md @@ -9,7 +9,7 @@ description: 'Enforce consistent usage of type exports.' TypeScript allows specifying a `type` keyword on exports to indicate that the export exists only in the type system, not at runtime. This allows transpilers to drop exports without knowing the types of the dependencies. -## Rule Details +## Examples @@ -21,9 +21,7 @@ interface ButtonProps { } class Button implements ButtonProps { - onClick() { - console.log('button!'); - } + onClick = () => console.log('button!'); } export { Button, ButtonProps }; @@ -35,11 +33,11 @@ export { Button, ButtonProps }; interface ButtonProps { onClick: () => void; } + class Button implements ButtonProps { - onClick() { - console.log('button!'); - } + onClick = () => console.log('button!'); } + export { Button }; export type { ButtonProps }; ``` diff --git a/packages/eslint-plugin/docs/rules/default-param-last.md b/packages/eslint-plugin/docs/rules/default-param-last.md index 9a0624fca227..e5902b200c03 100644 --- a/packages/eslint-plugin/docs/rules/default-param-last.md +++ b/packages/eslint-plugin/docs/rules/default-param-last.md @@ -6,7 +6,7 @@ description: 'Enforce default parameters to be last.' > > See **https://typescript-eslint.io/rules/default-param-last** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/default-param-last`](https://eslint.org/docs/rules/default-param-last) rule. It adds support for optional parameters. diff --git a/packages/eslint-plugin/docs/rules/dot-notation.md b/packages/eslint-plugin/docs/rules/dot-notation.md index 741de5ee5e71..e48e2c9a9b41 100644 --- a/packages/eslint-plugin/docs/rules/dot-notation.md +++ b/packages/eslint-plugin/docs/rules/dot-notation.md @@ -6,7 +6,7 @@ description: 'Enforce dot notation whenever possible.' > > See **https://typescript-eslint.io/rules/dot-notation** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/dot-notation`](https://eslint.org/docs/rules/dot-notation) rule. It adds: diff --git a/packages/eslint-plugin/docs/rules/explicit-function-return-type.md b/packages/eslint-plugin/docs/rules/explicit-function-return-type.md index 76a4d6a83f3b..3a67a7e23721 100644 --- a/packages/eslint-plugin/docs/rules/explicit-function-return-type.md +++ b/packages/eslint-plugin/docs/rules/explicit-function-return-type.md @@ -14,7 +14,7 @@ They can also speed up TypeScript type checking performance in large codebases w This rule enforces that functions do have an explicit return type annotation. -## Rule Details +## Examples diff --git a/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md b/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md index 35d0a64a8b00..2a300704db7b 100644 --- a/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md +++ b/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md @@ -13,8 +13,9 @@ Leaving off accessibility modifiers makes for less code to read and write. Members are `public` by default. However, adding in explicit accessibility modifiers can be helpful in codebases with many classes for enforcing proper privacy of members. +Some developers also find it preferable for code readability to keep member publicity explicit. -## Rule Details +## Examples This rule aims to make code more readable and explicit about who can use which properties. diff --git a/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md b/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md index ae5efb95c94f..2995d3b2c7ec 100644 --- a/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md +++ b/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md @@ -10,7 +10,7 @@ Explicit types for function return values and arguments makes it clear to any ca Adding explicit type annotations for those types can help improve code readability. It can also improve TypeScript type checking performance on larger codebases. -## Rule Details +## Examples diff --git a/packages/eslint-plugin/docs/rules/func-call-spacing.md b/packages/eslint-plugin/docs/rules/func-call-spacing.md index 74de5955e9b7..c30bbface282 100644 --- a/packages/eslint-plugin/docs/rules/func-call-spacing.md +++ b/packages/eslint-plugin/docs/rules/func-call-spacing.md @@ -6,7 +6,7 @@ description: 'Require or disallow spacing between function identifiers and their > > See **https://typescript-eslint.io/rules/func-call-spacing** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/func-call-spacing`](https://eslint.org/docs/rules/func-call-spacing) rule. It adds support for generic type parameters on function calls. diff --git a/packages/eslint-plugin/docs/rules/indent.md b/packages/eslint-plugin/docs/rules/indent.md index 6c16f6f0c21d..3d291c8b81ca 100644 --- a/packages/eslint-plugin/docs/rules/indent.md +++ b/packages/eslint-plugin/docs/rules/indent.md @@ -14,7 +14,7 @@ Please read [Issue #1824: Problems with the indent rule](https://github.com/type ::: -## Rule Details +## Examples This rule extends the base [`eslint/indent`](https://eslint.org/docs/rules/indent) rule. It adds support for TypeScript nodes. diff --git a/packages/eslint-plugin/docs/rules/init-declarations.md b/packages/eslint-plugin/docs/rules/init-declarations.md index 97fc51bc5c32..da086da83928 100644 --- a/packages/eslint-plugin/docs/rules/init-declarations.md +++ b/packages/eslint-plugin/docs/rules/init-declarations.md @@ -6,7 +6,7 @@ description: 'Require or disallow initialization in variable declarations.' > > See **https://typescript-eslint.io/rules/init-declarations** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/init-declarations`](https://eslint.org/docs/rules/init-declarations) rule. It adds support for TypeScript's `declare` variables. diff --git a/packages/eslint-plugin/docs/rules/keyword-spacing.md b/packages/eslint-plugin/docs/rules/keyword-spacing.md index 17f731cfc948..5fe8888ff99b 100644 --- a/packages/eslint-plugin/docs/rules/keyword-spacing.md +++ b/packages/eslint-plugin/docs/rules/keyword-spacing.md @@ -6,7 +6,7 @@ description: 'Enforce consistent spacing before and after keywords.' > > See **https://typescript-eslint.io/rules/keyword-spacing** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/keyword-spacing`](https://eslint.org/docs/rules/keyword-spacing) rule. This version adds support for generic type parameters on function calls. diff --git a/packages/eslint-plugin/docs/rules/lines-between-class-members.md b/packages/eslint-plugin/docs/rules/lines-between-class-members.md index f8d40de40899..13636d07a2cf 100644 --- a/packages/eslint-plugin/docs/rules/lines-between-class-members.md +++ b/packages/eslint-plugin/docs/rules/lines-between-class-members.md @@ -8,7 +8,7 @@ description: 'Require or disallow an empty line between class members.' This rule improves readability by enforcing lines between class members. It will not check empty lines before the first member and after the last member. This rule will require or disallow an empty line between class members. -## Rule Details +## Examples This rule extends the base [`eslint/lines-between-class-members`](https://eslint.org/docs/rules/lines-between-class-members) rule. It adds support for ignoring overload methods in a class. diff --git a/packages/eslint-plugin/docs/rules/member-delimiter-style.md b/packages/eslint-plugin/docs/rules/member-delimiter-style.md index c3fe53758d29..dae4f51f6296 100644 --- a/packages/eslint-plugin/docs/rules/member-delimiter-style.md +++ b/packages/eslint-plugin/docs/rules/member-delimiter-style.md @@ -56,7 +56,7 @@ type Bar = { The rule also enforces the presence (or absence) of the delimiter in the last member of the interface and/or type literal. Finally, this rule can enforce separate delimiter syntax for single line declarations. -## Rule Details +## Examples This rule aims to standardize the way interface and type literal members are delimited. diff --git a/packages/eslint-plugin/docs/rules/member-ordering.md b/packages/eslint-plugin/docs/rules/member-ordering.md index 62d35a8a444e..9a6ca8d5dbc8 100644 --- a/packages/eslint-plugin/docs/rules/member-ordering.md +++ b/packages/eslint-plugin/docs/rules/member-ordering.md @@ -6,8 +6,8 @@ description: 'Require a consistent member declaration order.' > > See **https://typescript-eslint.io/rules/member-ordering** for documentation. -This rule aims to standardize the way class declarations, class expressions, interfaces and type literals are structured and ordered. -A consistent ordering of fields, methods and constructors can make interfaces, type literals, classes and class expressions easier to read, navigate, and edit. +This rule aims to standardize the way classes, interfaces, and type literals are structured and ordered. +A consistent ordering of fields, methods and constructors can make code easier to read, navigate, and edit. ## Options diff --git a/packages/eslint-plugin/docs/rules/naming-convention.md b/packages/eslint-plugin/docs/rules/naming-convention.md index ef6d82e83029..50bd17515183 100644 --- a/packages/eslint-plugin/docs/rules/naming-convention.md +++ b/packages/eslint-plugin/docs/rules/naming-convention.md @@ -9,9 +9,7 @@ description: 'Enforce naming conventions for everything across a codebase.' Enforcing naming conventions helps keep the codebase consistent, and reduces overhead when thinking about how to name a variable. Additionally, a well-designed style guide can help communicate intent, such as by enforcing all private properties begin with an `_`, and all global-level constants are written in `UPPER_CASE`. -There are many different rules that have existed over time, but they have had the problem of not having enough granularity, meaning it was hard to have a well defined style guide, and most of the time you needed 3 or more rules at once to enforce different conventions, hoping they didn't conflict. - -## Rule Details +## Examples This rule allows you to enforce conventions for any identifier, using granular selectors to create a fine-grained style guide. diff --git a/packages/eslint-plugin/docs/rules/no-array-constructor.md b/packages/eslint-plugin/docs/rules/no-array-constructor.md index 54b69eb91ba1..c6b147752f2f 100644 --- a/packages/eslint-plugin/docs/rules/no-array-constructor.md +++ b/packages/eslint-plugin/docs/rules/no-array-constructor.md @@ -6,7 +6,7 @@ description: 'Disallow generic `Array` constructors.' > > See **https://typescript-eslint.io/rules/no-array-constructor** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-array-constructor`](https://eslint.org/docs/rules/no-array-constructor) rule. It adds support for the generically typed `Array` constructor (`new Array()`). diff --git a/packages/eslint-plugin/docs/rules/no-base-to-string.md b/packages/eslint-plugin/docs/rules/no-base-to-string.md index 857c82091f6a..453968828ce3 100644 --- a/packages/eslint-plugin/docs/rules/no-base-to-string.md +++ b/packages/eslint-plugin/docs/rules/no-base-to-string.md @@ -6,21 +6,19 @@ description: 'Require `.toString()` to only be called on objects which provide u > > See **https://typescript-eslint.io/rules/no-base-to-string** for documentation. -Requires `.toString()` to only be called on objects which provide useful information when stringified. - JavaScript will call `toString()` on an object when it is converted to a string, such as when `+` adding to a string or in `${}` template literals. +The default Object `.toString()` returns `"[object Object]"`, which is often not what was intended. +This rule requires stringified objects define a more useful `.toString()` method. -The default Object `.toString()` returns `"[object Object]"`, so this rule requires stringified objects define a more useful `.toString()` method. - -Note that `Function` provides its own `.toString()` that returns the function's code. -Functions are not flagged by this rule. +> This rule has some overlap with [`restrict-plus-operands`](./restrict-plus-operands.md) and [`restrict-template-expressions`](./restrict-template-expressions.md). -This rule has some overlap with [`restrict-plus-operands`](./restrict-plus-operands.md) and [`restrict-template-expressions`](./restrict-template-expressions.md). - -## Rule Details +## Examples This rule prevents accidentally defaulting to the base Object `.toString()` method. +> Note that `Function` provides its own `.toString()` that returns the function's code. +> Functions are not flagged by this rule. + ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-confusing-non-null-assertion.md b/packages/eslint-plugin/docs/rules/no-confusing-non-null-assertion.md index 1b67f558af50..34d474cf853c 100644 --- a/packages/eslint-plugin/docs/rules/no-confusing-non-null-assertion.md +++ b/packages/eslint-plugin/docs/rules/no-confusing-non-null-assertion.md @@ -6,8 +6,6 @@ description: 'Disallow non-null assertion in locations that may be confusing.' > > See **https://typescript-eslint.io/rules/no-confusing-non-null-assertion** for documentation. -## Rule Details - Using a non-null assertion (`!`) next to an assign or equals check (`=` or `==` or `===`) creates code that is confusing as it looks similar to a not equals check (`!=` `!==`). ```typescript @@ -16,6 +14,10 @@ a !== b; // not equals test(`!==`) a! === b; // a non-null assertions(`!`) and an triple equals test(`===`) ``` +This rule flags confusing `!` assertions and suggests either removing them or wrapping the asserted expression in `()` parenthesis. + +## Examples + ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-confusing-void-expression.md b/packages/eslint-plugin/docs/rules/no-confusing-void-expression.md index 4c4f6b1fa216..dbc0aaee9e83 100644 --- a/packages/eslint-plugin/docs/rules/no-confusing-void-expression.md +++ b/packages/eslint-plugin/docs/rules/no-confusing-void-expression.md @@ -6,12 +6,11 @@ description: 'Require expressions of type void to appear in statement position.' > > See **https://typescript-eslint.io/rules/no-confusing-void-expression** for documentation. -Returning the results of an expression whose type is void can be misleading. -Attempting to do so is likely a symptom of expecting a different return type from a function. -Even if used correctly, it can be misleading for other developers, -who don't know what a particular function does and if its result matters. +`void` in TypeScript refers to a function return that is meant to be ignored. +Attempting to use a `void`-typed value, such as storing the result of a called function in a variable, is often a sign of a programmer error. +`void` can also be misleading for other developers even if used correctly. -This rule provides automatic fixes for most common cases. +This rule prevents `void` type expressions from being used in misleading locations such as being assigned to a variable, provided as a function argument, or returned from a function. ## Examples diff --git a/packages/eslint-plugin/docs/rules/no-dupe-class-members.md b/packages/eslint-plugin/docs/rules/no-dupe-class-members.md index 2bfc1864f7e2..432ac55f0140 100644 --- a/packages/eslint-plugin/docs/rules/no-dupe-class-members.md +++ b/packages/eslint-plugin/docs/rules/no-dupe-class-members.md @@ -6,7 +6,7 @@ description: 'Disallow duplicate class members.' > > See **https://typescript-eslint.io/rules/no-dupe-class-members** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-dupe-class-members`](https://eslint.org/docs/rules/no-dupe-class-members) rule. It adds support for TypeScript's method overload definitions. diff --git a/packages/eslint-plugin/docs/rules/no-duplicate-enum-values.md b/packages/eslint-plugin/docs/rules/no-duplicate-enum-values.md index e65884f821f4..22b951a4a160 100644 --- a/packages/eslint-plugin/docs/rules/no-duplicate-enum-values.md +++ b/packages/eslint-plugin/docs/rules/no-duplicate-enum-values.md @@ -8,9 +8,12 @@ description: 'Disallow duplicate enum member values.' Although TypeScript supports duplicate enum member values, people usually expect members to have unique values within the same enum. Duplicate values can lead to bugs that are hard to track down. -## Rule Details +## Examples -This rule disallows defining an enum with multiple members initialized to the same value. Now it only enforces on enum members initialized with String or Number literals. Members without initializer or initialized with an expression are not checked by this rule. +This rule disallows defining an enum with multiple members initialized to the same value. + +> This rule only enforces on enum members initialized with string or number literals. +> Members without an initializer or initialized with an expression are not checked by this rule. diff --git a/packages/eslint-plugin/docs/rules/no-dynamic-delete.md b/packages/eslint-plugin/docs/rules/no-dynamic-delete.md index 78b1a1453bd1..e6afb335bc84 100644 --- a/packages/eslint-plugin/docs/rules/no-dynamic-delete.md +++ b/packages/eslint-plugin/docs/rules/no-dynamic-delete.md @@ -7,12 +7,12 @@ description: 'Disallow using the `delete` operator on computed key expressions.' > See **https://typescript-eslint.io/rules/no-dynamic-delete** for documentation. Deleting dynamically computed keys can be dangerous and in some cases not well optimized. - -## Rule Details - Using the `delete` operator on keys that aren't runtime constants could be a sign that you're using the wrong data structures. Using `Object`s with added and removed keys can cause occasional edge case bugs, such as if a key is named `"hasOwnProperty"`. -Consider using a `Map` or `Set` if you’re storing collections of objects. + +> Consider using a `Map` or `Set` if you’re storing collections of objects. + +## Examples diff --git a/packages/eslint-plugin/docs/rules/no-empty-function.md b/packages/eslint-plugin/docs/rules/no-empty-function.md index b889968c0718..529a8a2df7a9 100644 --- a/packages/eslint-plugin/docs/rules/no-empty-function.md +++ b/packages/eslint-plugin/docs/rules/no-empty-function.md @@ -6,7 +6,7 @@ description: 'Disallow empty functions.' > > See **https://typescript-eslint.io/rules/no-empty-function** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-empty-function`](https://eslint.org/docs/rules/no-empty-function) rule. It adds support for handling TypeScript specific code that would otherwise trigger the rule. diff --git a/packages/eslint-plugin/docs/rules/no-empty-interface.md b/packages/eslint-plugin/docs/rules/no-empty-interface.md index 17bebea168ff..194a6e6a654b 100644 --- a/packages/eslint-plugin/docs/rules/no-empty-interface.md +++ b/packages/eslint-plugin/docs/rules/no-empty-interface.md @@ -6,13 +6,13 @@ description: 'Disallow the declaration of empty interfaces.' > > See **https://typescript-eslint.io/rules/no-empty-interface** for documentation. -An empty interface is equivalent to its supertype. If the interface does not implement a supertype, then -the interface is equivalent to an empty object (`{}`). In both cases it can be omitted. - -## Rule Details +An empty interface in TypeScript does very little: any non-nullable value is assignable to `{}`. +Using an empty interface is often a sign of programmer error, such as misunderstanding the concept of `{}` or forgetting to fill in fields. This rule aims to ensure that only meaningful interfaces are declared in the code. +## Examples + ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-explicit-any.md b/packages/eslint-plugin/docs/rules/no-explicit-any.md index b32acb43902d..c2701453aca5 100644 --- a/packages/eslint-plugin/docs/rules/no-explicit-any.md +++ b/packages/eslint-plugin/docs/rules/no-explicit-any.md @@ -6,16 +6,12 @@ description: 'Disallow the `any` type.' > > See **https://typescript-eslint.io/rules/no-explicit-any** for documentation. -Using the `any` type defeats the purpose of using TypeScript. -When `any` is used, all compiler type checks around that value are ignored. +The `any` type in TypeScript is a dangerous "escape hatch" from the type system. +Using `any` disables many type checking rules and is generally considered only valid in rare edge cases or when prototyping code. -## Rule Details +> TypeScript's `--noImplicitAny` compiler option prevents an implied `any`, but doesn't prevent `any` from being explicitly used the way this rule does. -This rule doesn't allow `any` types to be defined. -It aims to keep TypeScript maximally useful. -TypeScript has a compiler flag for `--noImplicitAny` that will prevent -an `any` type from being implied by the compiler, but doesn't prevent -`any` from being explicitly used. +## Examples diff --git a/packages/eslint-plugin/docs/rules/no-extra-non-null-assertion.md b/packages/eslint-plugin/docs/rules/no-extra-non-null-assertion.md index 28b47a745319..db2c584827c7 100644 --- a/packages/eslint-plugin/docs/rules/no-extra-non-null-assertion.md +++ b/packages/eslint-plugin/docs/rules/no-extra-non-null-assertion.md @@ -1,14 +1,15 @@ --- -description: 'Disallow extra non-null assertion.' +description: 'Disallow extra non-null assertions.' --- > 🛑 This file is source code, not the primary documentation location! 🛑 > > See **https://typescript-eslint.io/rules/no-extra-non-null-assertion** for documentation. -## Rule Details +The `!` non-null assertion operator in TypeScript is used to assert that a value's type does not include `null` or `undefined`. +Using the operator any more than once on a single value does nothing. -Examples of code for this rule: +## Examples diff --git a/packages/eslint-plugin/docs/rules/no-extra-parens.md b/packages/eslint-plugin/docs/rules/no-extra-parens.md index 4bd89ac91b9c..0c5cc21941e2 100644 --- a/packages/eslint-plugin/docs/rules/no-extra-parens.md +++ b/packages/eslint-plugin/docs/rules/no-extra-parens.md @@ -6,7 +6,7 @@ description: 'Disallow unnecessary parentheses.' > > See **https://typescript-eslint.io/rules/no-extra-parens** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-extra-parens`](https://eslint.org/docs/rules/no-extra-parens) rule. It adds support for TypeScript type assertions. diff --git a/packages/eslint-plugin/docs/rules/no-extra-semi.md b/packages/eslint-plugin/docs/rules/no-extra-semi.md index a8f3cdca1b2e..086bd87f450a 100644 --- a/packages/eslint-plugin/docs/rules/no-extra-semi.md +++ b/packages/eslint-plugin/docs/rules/no-extra-semi.md @@ -6,7 +6,7 @@ description: 'Disallow unnecessary semicolons.' > > See **https://typescript-eslint.io/rules/no-extra-semi** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-extra-semi`](https://eslint.org/docs/rules/no-extra-semi) rule. It adds support for class properties. diff --git a/packages/eslint-plugin/docs/rules/no-extraneous-class.md b/packages/eslint-plugin/docs/rules/no-extraneous-class.md index 2efb49e95564..4cf0a2c67ada 100644 --- a/packages/eslint-plugin/docs/rules/no-extraneous-class.md +++ b/packages/eslint-plugin/docs/rules/no-extraneous-class.md @@ -6,23 +6,21 @@ description: 'Disallow classes used as namespaces.' > > See **https://typescript-eslint.io/rules/no-extraneous-class** for documentation. -This rule warns when a class has no non-static members, such as for a class used exclusively as a static namespace. - -## Rule Details +This rule reports when a class has no non-static members, such as for a class used exclusively as a static namespace. Users who come from a [OOP](https://en.wikipedia.org/wiki/Object-oriented_programming) paradigm may wrap their utility functions in an extra class, instead of putting them at the top level of an ECMAScript module. Doing so is generally unnecessary in JavaScript and TypeScript projects. - Wrapper classes add extra cognitive complexity to code without adding any structural improvements - Whatever would be put on them, such as utility functions, are already organized by virtue of being in a module. - - As an alternative, you can always `import * as ...` the module to get all of them in a single object. + - As an alternative, you can `import * as ...` the module to get all of them in a single object. - IDEs can't provide as good suggestions for static class or namespace imported properties when you start typing property names - It's more difficult to statically analyze code for unused variables, etc. when they're all on the class (see: [Finding dead code (and dead types) in TypeScript](https://effectivetypescript.com/2020/10/20/tsprune)). -This rule also flags classes that have only a constructor and no fields. +This rule also reports classes that have only a constructor and no fields. Those classes can generally be replaced with a standalone function. -Examples of code for this rule: +## Examples diff --git a/packages/eslint-plugin/docs/rules/no-floating-promises.md b/packages/eslint-plugin/docs/rules/no-floating-promises.md index 09e86b853086..0e19e3642bf4 100644 --- a/packages/eslint-plugin/docs/rules/no-floating-promises.md +++ b/packages/eslint-plugin/docs/rules/no-floating-promises.md @@ -22,9 +22,7 @@ Valid ways of handling a Promise-valued statement include: See [`no-misused-promises`](./no-misused-promises.md) for detecting code that provides Promises to _logical_ locations such as if statements. ::: -## Rule Details - -Examples of code for this rule: +## Examples diff --git a/packages/eslint-plugin/docs/rules/no-for-in-array.md b/packages/eslint-plugin/docs/rules/no-for-in-array.md index f046ff8ddd6b..9cf2ca3f54ae 100644 --- a/packages/eslint-plugin/docs/rules/no-for-in-array.md +++ b/packages/eslint-plugin/docs/rules/no-for-in-array.md @@ -8,7 +8,7 @@ description: 'Disallow iterating over an array with a for-in loop.' This rule prohibits iterating over an array with a for-in loop. -## Rule Details +## Examples A for-in loop (`for (var k in o)`) iterates over the properties of an Object. While it is legal to use for-in loops with array types, it is not common. @@ -23,8 +23,6 @@ for (const [index, value] of array.entries()) { ... } for (let i = 0; i < array.length; i++) { ... } ``` -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-implicit-any-catch.md b/packages/eslint-plugin/docs/rules/no-implicit-any-catch.md index 943e2c75b21b..ea75c9818902 100644 --- a/packages/eslint-plugin/docs/rules/no-implicit-any-catch.md +++ b/packages/eslint-plugin/docs/rules/no-implicit-any-catch.md @@ -19,12 +19,10 @@ The `noImplicitAny` flag in TypeScript does not cover this for backwards compati ## DEPRECATED -## Rule Details +## Examples This rule requires an explicit type to be declared on a catch clause variable. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-implied-eval.md b/packages/eslint-plugin/docs/rules/no-implied-eval.md index 9f3ad17180f7..918b6a12e755 100644 --- a/packages/eslint-plugin/docs/rules/no-implied-eval.md +++ b/packages/eslint-plugin/docs/rules/no-implied-eval.md @@ -25,12 +25,10 @@ passed in to be interpreted. The same can be done with `setInterval()`, `setImme The best practice is to avoid using `new Function()` or `execScript()` and always use a function for the first argument of `setTimeout()`, `setInterval()` and `setImmediate()`. -## Rule Details +## Examples This rule aims to eliminate implied `eval()` through the use of `new Function()`, `setTimeout()`, `setInterval()`, `setImmediate()` or `execScript()`. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-inferrable-types.md b/packages/eslint-plugin/docs/rules/no-inferrable-types.md index a29427a33cfb..b26ceb62908a 100644 --- a/packages/eslint-plugin/docs/rules/no-inferrable-types.md +++ b/packages/eslint-plugin/docs/rules/no-inferrable-types.md @@ -8,7 +8,7 @@ description: 'Disallow explicit type declarations for variables or parameters in Explicit types where they can be easily inferred may add unnecessary verbosity. -## Rule Details +## Examples This rule disallows explicit type declarations on parameters, variables and properties where the type can be easily inferred from its value. diff --git a/packages/eslint-plugin/docs/rules/no-invalid-this.md b/packages/eslint-plugin/docs/rules/no-invalid-this.md index 53e0f68fa9f0..4d6abe81f705 100644 --- a/packages/eslint-plugin/docs/rules/no-invalid-this.md +++ b/packages/eslint-plugin/docs/rules/no-invalid-this.md @@ -6,7 +6,7 @@ description: 'Disallow `this` keywords outside of classes or class-like objects. > > See **https://typescript-eslint.io/rules/no-invalid-this** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-invalid-this`](https://eslint.org/docs/rules/no-invalid-this) rule. It adds support for TypeScript's `this` parameters. diff --git a/packages/eslint-plugin/docs/rules/no-invalid-void-type.md b/packages/eslint-plugin/docs/rules/no-invalid-void-type.md index a36919363715..14403638ac9c 100644 --- a/packages/eslint-plugin/docs/rules/no-invalid-void-type.md +++ b/packages/eslint-plugin/docs/rules/no-invalid-void-type.md @@ -16,12 +16,10 @@ in contrast with implicit `undefined` type which means that a function returns a So “nothing” cannot be mixed with any other types, other than `never`, which accepts all types. If you need this - use the `undefined` type instead. -## Rule Details +## Examples This rule aims to ensure that the `void` type is only used in valid places. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-loop-func.md b/packages/eslint-plugin/docs/rules/no-loop-func.md index 753eb115cfbb..e2ba64a8ecdb 100644 --- a/packages/eslint-plugin/docs/rules/no-loop-func.md +++ b/packages/eslint-plugin/docs/rules/no-loop-func.md @@ -6,7 +6,7 @@ description: 'Disallow function declarations that contain unsafe references insi > > See **https://typescript-eslint.io/rules/no-loop-func** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-loop-func`](https://eslint.org/docs/rules/no-loop-func) rule. It adds support for TypeScript types. diff --git a/packages/eslint-plugin/docs/rules/no-loss-of-precision.md b/packages/eslint-plugin/docs/rules/no-loss-of-precision.md index 62e263219e85..f8db7ef60211 100644 --- a/packages/eslint-plugin/docs/rules/no-loss-of-precision.md +++ b/packages/eslint-plugin/docs/rules/no-loss-of-precision.md @@ -6,7 +6,7 @@ description: 'Disallow literal numbers that lose precision.' > > See **https://typescript-eslint.io/rules/no-loss-of-precision** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-loss-of-precision`](https://eslint.org/docs/rules/no-loss-of-precision) rule. It adds support for [numeric separators](https://github.com/tc39/proposal-numeric-separator). diff --git a/packages/eslint-plugin/docs/rules/no-magic-numbers.md b/packages/eslint-plugin/docs/rules/no-magic-numbers.md index 7af0e561536a..258af4dd4cf5 100644 --- a/packages/eslint-plugin/docs/rules/no-magic-numbers.md +++ b/packages/eslint-plugin/docs/rules/no-magic-numbers.md @@ -6,7 +6,7 @@ description: 'Disallow magic numbers.' > > See **https://typescript-eslint.io/rules/no-magic-numbers** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-magic-numbers`](https://eslint.org/docs/rules/no-magic-numbers) rule. It adds support for: diff --git a/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.md b/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.md index d99347a75141..1563f3b69b28 100644 --- a/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.md +++ b/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.md @@ -8,14 +8,12 @@ description: 'Disallow the `void` operator except when used to discard a value.' Disallows the `void` operator when its argument is already of type `void` or `undefined`. -## Rule Details +## Examples The `void` operator is a useful tool to convey the programmer's intent to discard a value. For example, it is recommended as one way of suppressing [`@typescript-eslint/no-floating-promises`](./no-floating-promises.md) instead of adding `.catch()` to a promise. This rule helps an author catch API changes where previously a value was being discarded at a call site, but the callee changed so it no longer returns a value. When combined with [no-unused-expressions](https://eslint.org/docs/rules/no-unused-expressions), it also helps _readers_ of the code by ensuring consistency: a statement that looks like `void foo();` is **always** discarding a return value, and a statement that looks like `foo();` is **never** discarding a return value. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-misused-new.md b/packages/eslint-plugin/docs/rules/no-misused-new.md index 08459fba7962..45e8e5723cb7 100644 --- a/packages/eslint-plugin/docs/rules/no-misused-new.md +++ b/packages/eslint-plugin/docs/rules/no-misused-new.md @@ -8,9 +8,7 @@ description: 'Enforce valid definition of `new` and `constructor`.' Warns on apparent attempts to define constructors for interfaces or `new` for classes. -## Rule Details - -Examples of code for this rule: +## Examples diff --git a/packages/eslint-plugin/docs/rules/no-misused-promises.md b/packages/eslint-plugin/docs/rules/no-misused-promises.md index 6e75b5db103f..2b2f512a1c1b 100644 --- a/packages/eslint-plugin/docs/rules/no-misused-promises.md +++ b/packages/eslint-plugin/docs/rules/no-misused-promises.md @@ -15,7 +15,7 @@ functions are handled/awaited. See [`no-floating-promises`](./no-floating-promises.md) for detecting unhandled Promise _statements_. ::: -## Rule Details +## Examples This rule accepts a single option which is an object with `checksConditionals`, `checksVoidReturn`, and `checksSpreads` properties indicating which types of diff --git a/packages/eslint-plugin/docs/rules/no-namespace.md b/packages/eslint-plugin/docs/rules/no-namespace.md index 6e4bda690bef..5ef63e7b127f 100644 --- a/packages/eslint-plugin/docs/rules/no-namespace.md +++ b/packages/eslint-plugin/docs/rules/no-namespace.md @@ -11,7 +11,7 @@ ways to organize TypeScript code. ES2015 module syntax is now preferred (`import This rule still allows the use of TypeScript module declarations to describe external APIs (`declare module 'foo' {}`). -## Rule Details +## Examples This rule aims to standardize the way modules are declared. diff --git a/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md b/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md index 19fd65779f8f..77c05fa084db 100644 --- a/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md +++ b/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md @@ -6,13 +6,11 @@ description: 'Disallow non-null assertions in the left operand of a nullish coal > > See **https://typescript-eslint.io/rules/no-non-null-asserted-nullish-coalescing** for documentation. -## Rule Details +## Examples The nullish coalescing operator is designed to provide a default value when dealing with `null` or `undefined`. Using non-null assertions in the left operand of the nullish coalescing operator is redundant. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-non-null-asserted-optional-chain.md b/packages/eslint-plugin/docs/rules/no-non-null-asserted-optional-chain.md index 89f9a3c87b76..5b4a15c21055 100644 --- a/packages/eslint-plugin/docs/rules/no-non-null-asserted-optional-chain.md +++ b/packages/eslint-plugin/docs/rules/no-non-null-asserted-optional-chain.md @@ -6,13 +6,11 @@ description: 'Disallow non-null assertions after an optional chain expression.' > > See **https://typescript-eslint.io/rules/no-non-null-asserted-optional-chain** for documentation. -## Rule Details +## Examples Optional chain expressions are designed to return `undefined` if the optional property is nullish. Using non-null assertions after an optional chain expression is wrong, and introduces a serious type safety hole into your code. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-non-null-assertion.md b/packages/eslint-plugin/docs/rules/no-non-null-assertion.md index 6e60483bc54d..874e1ea3739b 100644 --- a/packages/eslint-plugin/docs/rules/no-non-null-assertion.md +++ b/packages/eslint-plugin/docs/rules/no-non-null-assertion.md @@ -6,12 +6,10 @@ description: 'Disallow non-null assertions using the `!` postfix operator.' > > See **https://typescript-eslint.io/rules/no-non-null-assertion** for documentation. -## Rule Details +## Examples Using non-null assertions cancels the benefits of the strict null-checking mode. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-parameter-properties.md b/packages/eslint-plugin/docs/rules/no-parameter-properties.md index 2468cc5838ac..16a91864d590 100644 --- a/packages/eslint-plugin/docs/rules/no-parameter-properties.md +++ b/packages/eslint-plugin/docs/rules/no-parameter-properties.md @@ -14,7 +14,7 @@ This rule has been deprecated in favour of the equivalent, better named [`parame Parameter properties can be confusing to those new to TypeScript as they are less explicit than other ways of declaring and initializing class members. -## Rule Details +## Examples This rule disallows the use of parameter properties in constructors, forcing the user to explicitly declare all properties in the class. diff --git a/packages/eslint-plugin/docs/rules/no-redeclare.md b/packages/eslint-plugin/docs/rules/no-redeclare.md index b51ba369ce51..faef214667cf 100644 --- a/packages/eslint-plugin/docs/rules/no-redeclare.md +++ b/packages/eslint-plugin/docs/rules/no-redeclare.md @@ -6,7 +6,7 @@ description: 'Disallow variable redeclaration.' > > See **https://typescript-eslint.io/rules/no-redeclare** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-redeclare`](https://eslint.org/docs/rules/no-redeclare) rule. It adds support for TypeScript function overloads, and declaration merging. diff --git a/packages/eslint-plugin/docs/rules/no-redundant-type-constituents.md b/packages/eslint-plugin/docs/rules/no-redundant-type-constituents.md index 3cf63d4df491..d8c3a677a944 100644 --- a/packages/eslint-plugin/docs/rules/no-redundant-type-constituents.md +++ b/packages/eslint-plugin/docs/rules/no-redundant-type-constituents.md @@ -6,7 +6,7 @@ description: 'Disallow members of unions and intersections that do nothing or ov > > See **https://typescript-eslint.io/rules/no-redundant-type-constituents** for documentation. -## Rule Details +## Examples Some types can override some other types ("constituents") in a union or intersection and/or be overridden by some other types. TypeScript's set theory of types includes cases where a constituent type might be useless in the parent union or intersection. @@ -24,8 +24,6 @@ Within `&` intersections: - literal types "override" any primitive types in an intersection - literal types such as `""` "override" any of their primitive types such as `string` -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-require-imports.md b/packages/eslint-plugin/docs/rules/no-require-imports.md index b38486837e18..e8913526fcad 100644 --- a/packages/eslint-plugin/docs/rules/no-require-imports.md +++ b/packages/eslint-plugin/docs/rules/no-require-imports.md @@ -8,9 +8,7 @@ description: 'Disallow invocation of `require()`.' Prefer the newer ES6-style imports over `require()`. -## Rule Details - -Examples of code for this rule: +## Examples diff --git a/packages/eslint-plugin/docs/rules/no-restricted-imports.md b/packages/eslint-plugin/docs/rules/no-restricted-imports.md index 202143581f22..900a9cdd0307 100644 --- a/packages/eslint-plugin/docs/rules/no-restricted-imports.md +++ b/packages/eslint-plugin/docs/rules/no-restricted-imports.md @@ -6,7 +6,7 @@ description: 'Disallow specified modules when loaded by `import`.' > > See **https://typescript-eslint.io/rules/no-restricted-imports** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-restricted-imports`](https://eslint.org/docs/rules/no-restricted-imports) rule. diff --git a/packages/eslint-plugin/docs/rules/no-shadow.md b/packages/eslint-plugin/docs/rules/no-shadow.md index c990ff97230e..3adb286e317f 100644 --- a/packages/eslint-plugin/docs/rules/no-shadow.md +++ b/packages/eslint-plugin/docs/rules/no-shadow.md @@ -6,7 +6,7 @@ description: 'Disallow variable declarations from shadowing variables declared i > > See **https://typescript-eslint.io/rules/no-shadow** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-shadow`](https://eslint.org/docs/rules/no-shadow) rule. It adds support for TypeScript's `this` parameters and global augmentation, and adds options for TypeScript features. diff --git a/packages/eslint-plugin/docs/rules/no-this-alias.md b/packages/eslint-plugin/docs/rules/no-this-alias.md index 8ba520d7af68..ea8006117989 100644 --- a/packages/eslint-plugin/docs/rules/no-this-alias.md +++ b/packages/eslint-plugin/docs/rules/no-this-alias.md @@ -8,7 +8,7 @@ description: 'Disallow aliasing `this`.' This rule prohibits assigning variables to `this`. -## Rule Details +## Examples Assigning a variable to `this` instead of properly using arrow lambdas may be a symptom of pre-ES6 practices or not managing scope well. diff --git a/packages/eslint-plugin/docs/rules/no-throw-literal.md b/packages/eslint-plugin/docs/rules/no-throw-literal.md index 9fb71fcbe493..f4d189067b96 100644 --- a/packages/eslint-plugin/docs/rules/no-throw-literal.md +++ b/packages/eslint-plugin/docs/rules/no-throw-literal.md @@ -11,12 +11,10 @@ The fundamental benefit of `Error` objects is that they automatically keep track This rule restricts what can be thrown as an exception. When it was first created, it only prevented literals from being thrown (hence the name), but it has now been expanded to only allow expressions which have a possibility of being an `Error` object. With the `allowThrowingAny` and `allowThrowingUnknown`, it can be configured to only allow throwing values which are guaranteed to be an instance of `Error`. -## Rule Details +## Examples This rule is aimed at maintaining consistency when throwing exception by disallowing to throw literals and other expressions which cannot possibly be an `Error` object. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-type-alias.md b/packages/eslint-plugin/docs/rules/no-type-alias.md index 4117d6133451..a9774ebdde1a 100644 --- a/packages/eslint-plugin/docs/rules/no-type-alias.md +++ b/packages/eslint-plugin/docs/rules/no-type-alias.md @@ -78,7 +78,7 @@ On the other hand, using a type alias as an interface can limit your ability to: Finally, mapping types is an advanced technique and leaving it open can quickly become a pain point in your application. -## Rule Details +## Examples This rule disallows the use of type aliases in favor of interfaces and simplified types (primitives, tuples, unions, intersections, etc). diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md b/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md index 8e148460a42b..693b45e8267a 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md @@ -8,7 +8,7 @@ description: 'Disallow unnecessary equality comparisons against boolean literals Comparing boolean values to boolean literals is unnecessary, those comparisons result in the same booleans. Using the boolean values directly, or via a unary negation (`!value`), is more concise and clearer. -## Rule Details +## Examples This rule ensures that you do not include unnecessary comparisons with boolean literals. A comparison is considered unnecessary if it checks a boolean literal against any variable with just the `boolean` type. @@ -24,8 +24,6 @@ distinguish between strict and loose equality. Any example below that uses `===` would be treated the same way if `==` was used, and any example below that uses `!==` would be treated the same way if `!=` was used. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-condition.md b/packages/eslint-plugin/docs/rules/no-unnecessary-condition.md index ac50dc295f3a..1a55124991bc 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-condition.md +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-condition.md @@ -14,9 +14,7 @@ The following expressions are checked: - Conditions for `if`, `for`, `while`, and `do-while` statements - Base values of optional chain expressions -## Rule Details - -Examples of code for this rule: +## Examples diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-qualifier.md b/packages/eslint-plugin/docs/rules/no-unnecessary-qualifier.md index 58a2b80bf5d8..22a410158852 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-qualifier.md +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-qualifier.md @@ -6,13 +6,11 @@ description: 'Disallow unnecessary namespace qualifiers.' > > See **https://typescript-eslint.io/rules/no-unnecessary-qualifier** for documentation. -## Rule Details +## Examples This rule aims to let users know when a namespace or enum qualifier is unnecessary, whether used for a type or for a value. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-type-arguments.md b/packages/eslint-plugin/docs/rules/no-unnecessary-type-arguments.md index 976cf23e372a..2f24af3cd95b 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-type-arguments.md +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-type-arguments.md @@ -8,7 +8,7 @@ description: 'Disallow type arguments that are equal to the default.' Warns if an explicitly specified type argument is the default for that type parameter. -## Rule Details +## Examples Type parameters in TypeScript may specify a default value. For example: @@ -19,8 +19,6 @@ function f() {} It is redundant to provide an explicit type parameter equal to that default. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.md b/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.md index 30e81b4c9b69..c33ce0010c17 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.md +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.md @@ -8,12 +8,10 @@ description: 'Disallow type assertions that do not change the type of an express This rule prohibits using a type assertion that does not change the type of an expression. -## Rule Details +## Examples This rule aims to prevent unnecessary type assertions. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-type-constraint.md b/packages/eslint-plugin/docs/rules/no-unnecessary-type-constraint.md index c5b078810fa4..07ec4b536d22 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-type-constraint.md +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-type-constraint.md @@ -6,7 +6,7 @@ description: 'Disallow unnecessary constraints on generic types.' > > See **https://typescript-eslint.io/rules/no-unnecessary-type-constraint** for documentation. -## Rule Details +## Examples Type parameters (``) may be "constrained" with an `extends` keyword ([docs](https://www.typescriptlang.org/docs/handbook/generics.html#generic-constraints)). When not provided, type parameters happen to default to: @@ -16,8 +16,6 @@ When not provided, type parameters happen to default to: It is therefore redundant to `extend` from these types in later versions of TypeScript. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-argument.md b/packages/eslint-plugin/docs/rules/no-unsafe-argument.md index 63068ce497c6..e2f0807ffdd1 100644 --- a/packages/eslint-plugin/docs/rules/no-unsafe-argument.md +++ b/packages/eslint-plugin/docs/rules/no-unsafe-argument.md @@ -9,14 +9,12 @@ description: 'Disallow calling a function with a value with type `any`.' Despite your best intentions, the `any` type can sometimes leak into your codebase. Call a function with `any` typed argument are not checked at all by TypeScript, so it creates a potential safety hole, and source of bugs in your codebase. -## Rule Details +## Examples This rule disallows calling a function with `any` in its arguments, and it will disallow spreading `any[]`. This rule also disallows spreading a tuple type with one of its elements typed as `any`. This rule also compares the argument's type to the variable's type to ensure you don't pass an unsafe `any` in a generic position to a receiver that's expecting a specific type. For example, it will error if you assign `Set` to an argument declared as `Set`. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-assignment.md b/packages/eslint-plugin/docs/rules/no-unsafe-assignment.md index 9e797f4319f5..1d1d4808824e 100644 --- a/packages/eslint-plugin/docs/rules/no-unsafe-assignment.md +++ b/packages/eslint-plugin/docs/rules/no-unsafe-assignment.md @@ -9,13 +9,11 @@ description: 'Disallow assigning a value with type `any` to variables and proper Despite your best intentions, the `any` type can sometimes leak into your codebase. Assigning an `any` typed value to a variable can be hard to pick up on, particularly if it leaks in from an external library. Operations on the variable will not be checked at all by TypeScript, so it creates a potential safety hole, and source of bugs in your codebase. -## Rule Details +## Examples This rule disallows assigning `any` to a variable, and assigning `any[]` to an array destructuring. This rule also compares the assigned type to the variable's type to ensure you don't assign an unsafe `any` in a generic position to a receiver that's expecting a specific type. For example, it will error if you assign `Set` to a variable declared as `Set`. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-call.md b/packages/eslint-plugin/docs/rules/no-unsafe-call.md index 9191dca9ae86..a04a734d8775 100644 --- a/packages/eslint-plugin/docs/rules/no-unsafe-call.md +++ b/packages/eslint-plugin/docs/rules/no-unsafe-call.md @@ -9,12 +9,10 @@ description: 'Disallow calling a value with type `any`.' Despite your best intentions, the `any` type can sometimes leak into your codebase. The arguments to, and return value of calling an `any` typed variable are not checked at all by TypeScript, so it creates a potential safety hole, and source of bugs in your codebase. -## Rule Details +## Examples This rule disallows calling any variable that is typed as `any`. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-member-access.md b/packages/eslint-plugin/docs/rules/no-unsafe-member-access.md index 393a4bb46cdd..5aa7a6af67d7 100644 --- a/packages/eslint-plugin/docs/rules/no-unsafe-member-access.md +++ b/packages/eslint-plugin/docs/rules/no-unsafe-member-access.md @@ -9,12 +9,10 @@ description: 'Disallow member access on a value with type `any`.' Despite your best intentions, the `any` type can sometimes leak into your codebase. Member access on `any` typed variables is not checked at all by TypeScript, so it creates a potential safety hole, and source of bugs in your codebase. -## Rule Details +## Examples This rule disallows member access on any variable that is typed as `any`. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-return.md b/packages/eslint-plugin/docs/rules/no-unsafe-return.md index 9c5537229590..17c1a6f6bc2a 100644 --- a/packages/eslint-plugin/docs/rules/no-unsafe-return.md +++ b/packages/eslint-plugin/docs/rules/no-unsafe-return.md @@ -9,13 +9,11 @@ description: 'Disallow returning a value with type `any` from a function.' Despite your best intentions, the `any` type can sometimes leak into your codebase. Returned `any` typed values are not checked at all by TypeScript, so it creates a potential safety hole, and source of bugs in your codebase. -## Rule Details +## Examples This rule disallows returning `any` or `any[]` from a function. This rule also compares the return type to the function's declared/inferred return type to ensure you don't return an unsafe `any` in a generic position to a receiver that's expecting a specific type. For example, it will error if you return `Set` from a function declared as returning `Set`. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-unused-expressions.md b/packages/eslint-plugin/docs/rules/no-unused-expressions.md index db3120db3e25..4e439431d450 100644 --- a/packages/eslint-plugin/docs/rules/no-unused-expressions.md +++ b/packages/eslint-plugin/docs/rules/no-unused-expressions.md @@ -6,7 +6,7 @@ description: 'Disallow unused expressions.' > > See **https://typescript-eslint.io/rules/no-unused-expressions** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-unused-expressions`](https://eslint.org/docs/rules/no-unused-expressions) rule. It adds support for optional call expressions `x?.()`, and directive in module declarations. diff --git a/packages/eslint-plugin/docs/rules/no-unused-vars.md b/packages/eslint-plugin/docs/rules/no-unused-vars.md index ffd1ceb0f6a5..8fd90f74ae5a 100644 --- a/packages/eslint-plugin/docs/rules/no-unused-vars.md +++ b/packages/eslint-plugin/docs/rules/no-unused-vars.md @@ -6,7 +6,7 @@ description: 'Disallow unused variables.' > > See **https://typescript-eslint.io/rules/no-unused-vars** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-unused-vars`](https://eslint.org/docs/rules/no-unused-vars) rule. It adds support for TypeScript features, such as types. diff --git a/packages/eslint-plugin/docs/rules/no-use-before-define.md b/packages/eslint-plugin/docs/rules/no-use-before-define.md index e17a8b873e37..0350658347aa 100644 --- a/packages/eslint-plugin/docs/rules/no-use-before-define.md +++ b/packages/eslint-plugin/docs/rules/no-use-before-define.md @@ -6,7 +6,7 @@ description: 'Disallow the use of variables before they are defined.' > > See **https://typescript-eslint.io/rules/no-use-before-define** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-use-before-define`](https://eslint.org/docs/rules/no-use-before-define) rule. It adds support for `type`, `interface` and `enum` declarations. diff --git a/packages/eslint-plugin/docs/rules/no-useless-constructor.md b/packages/eslint-plugin/docs/rules/no-useless-constructor.md index e1a8297fefe7..0f570ab9e59d 100644 --- a/packages/eslint-plugin/docs/rules/no-useless-constructor.md +++ b/packages/eslint-plugin/docs/rules/no-useless-constructor.md @@ -6,7 +6,7 @@ description: 'Disallow unnecessary constructors.' > > See **https://typescript-eslint.io/rules/no-useless-constructor** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/no-useless-constructor`](https://eslint.org/docs/rules/no-useless-constructor) rule. It adds support for: diff --git a/packages/eslint-plugin/docs/rules/no-useless-empty-export.md b/packages/eslint-plugin/docs/rules/no-useless-empty-export.md index bf0f2b94ff2d..aaf2b08792a2 100644 --- a/packages/eslint-plugin/docs/rules/no-useless-empty-export.md +++ b/packages/eslint-plugin/docs/rules/no-useless-empty-export.md @@ -6,7 +6,7 @@ description: "Disallow empty exports that don't change anything in a module file > > See **https://typescript-eslint.io/rules/no-useless-empty-export** for documentation. -## Rule Details +## Examples An empty `export {}` statement is sometimes useful in TypeScript code to turn a file that would otherwise be a script file into a module file. Per the TypeScript Handbook [Modules](https://www.typescriptlang.org/docs/handbook/modules.html) page: @@ -16,8 +16,6 @@ Per the TypeScript Handbook [Modules](https://www.typescriptlang.org/docs/handbo However, an `export {}` statement does nothing if there are any other top-level import or export statements in a file. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-var-requires.md b/packages/eslint-plugin/docs/rules/no-var-requires.md index f7c0f8b8fb50..352da6f5a9f7 100644 --- a/packages/eslint-plugin/docs/rules/no-var-requires.md +++ b/packages/eslint-plugin/docs/rules/no-var-requires.md @@ -8,9 +8,7 @@ description: 'Disallow `require` statements except in import statements.' In other words, the use of forms such as `var foo = require("foo")` are banned. Instead use ES6 style imports or `import foo = require("foo")` imports. -## Rule Details - -Examples of code for this rule: +## Examples diff --git a/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.md b/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.md index c6aaa0913248..662a99880be8 100644 --- a/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.md +++ b/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.md @@ -8,9 +8,7 @@ description: 'Enforce non-null assertions over explicit type casts.' This rule detects when an `as` cast is doing the same job as a `!` would, and suggests fixing the code to be an `!`. -## Rule Details - -Examples of code for this rule: +## Examples diff --git a/packages/eslint-plugin/docs/rules/object-curly-spacing.md b/packages/eslint-plugin/docs/rules/object-curly-spacing.md index 9dcf431db32c..1b333cae45e9 100644 --- a/packages/eslint-plugin/docs/rules/object-curly-spacing.md +++ b/packages/eslint-plugin/docs/rules/object-curly-spacing.md @@ -6,7 +6,7 @@ description: 'Enforce consistent spacing inside braces.' > > See **https://typescript-eslint.io/rules/object-curly-spacing** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/object-curly-spacing`](https://eslint.org/docs/rules/object-curly-spacing) rule. It adds support for TypeScript's object types. diff --git a/packages/eslint-plugin/docs/rules/padding-line-between-statements.md b/packages/eslint-plugin/docs/rules/padding-line-between-statements.md index d3687c11a22d..5387cacac361 100644 --- a/packages/eslint-plugin/docs/rules/padding-line-between-statements.md +++ b/packages/eslint-plugin/docs/rules/padding-line-between-statements.md @@ -6,7 +6,7 @@ description: 'Require or disallow padding lines between statements.' > > See **https://typescript-eslint.io/rules/padding-line-between-statements** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/padding-line-between-statements`](https://eslint.org/docs/rules/padding-line-between-statements) rule. It adds support for TypeScript constructs such as `interface` and `type`. diff --git a/packages/eslint-plugin/docs/rules/parameter-properties.md b/packages/eslint-plugin/docs/rules/parameter-properties.md index e41e1bbd5df6..383a432b08ac 100644 --- a/packages/eslint-plugin/docs/rules/parameter-properties.md +++ b/packages/eslint-plugin/docs/rules/parameter-properties.md @@ -9,7 +9,7 @@ description: 'Require or disallow parameter properties in class constructors.' Parameter properties can be confusing to those new to TypeScript as they are less explicit than other ways of declaring and initializing class members. -## Rule Details +## Examples This rule disallows the use of parameter properties in constructors, forcing the user to explicitly declare all properties in the class. diff --git a/packages/eslint-plugin/docs/rules/prefer-as-const.md b/packages/eslint-plugin/docs/rules/prefer-as-const.md index ce930aa3390a..9f2ce9ba2744 100644 --- a/packages/eslint-plugin/docs/rules/prefer-as-const.md +++ b/packages/eslint-plugin/docs/rules/prefer-as-const.md @@ -8,9 +8,7 @@ description: 'Enforce the use of `as const` over literal type.' This rule recommends usage of `const` assertion when type primitive value is equal to type. -## Rule Details - -Examples of code for this rule: +## Examples diff --git a/packages/eslint-plugin/docs/rules/prefer-enum-initializers.md b/packages/eslint-plugin/docs/rules/prefer-enum-initializers.md index 08e19754b2b6..7950e704dce5 100644 --- a/packages/eslint-plugin/docs/rules/prefer-enum-initializers.md +++ b/packages/eslint-plugin/docs/rules/prefer-enum-initializers.md @@ -10,7 +10,7 @@ This rule recommends having each `enum`s member value explicitly initialized. `enum`s are a practical way to organize semantically related constant values. However, by implicitly defining values, `enum`s can lead to unexpected bugs if it's modified without paying attention to the order of its items. -## Rule Details +## Examples `enum`s infers sequential numbers automatically when initializers are omitted: @@ -31,8 +31,6 @@ enum Status { } ``` -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/prefer-for-of.md b/packages/eslint-plugin/docs/rules/prefer-for-of.md index 815059bcc9a5..13c36bc191f9 100644 --- a/packages/eslint-plugin/docs/rules/prefer-for-of.md +++ b/packages/eslint-plugin/docs/rules/prefer-for-of.md @@ -8,12 +8,10 @@ description: 'Enforce the use of `for-of` loop over the standard `for` loop wher This rule recommends a for-of loop when the loop index is only used to read from an array that is being iterated. -## Rule Details +## Examples For cases where the index is only used to read from the array being iterated, a for-of loop is easier to read and write. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/prefer-function-type.md b/packages/eslint-plugin/docs/rules/prefer-function-type.md index 1ba1cf22a2cc..40980f0d7250 100644 --- a/packages/eslint-plugin/docs/rules/prefer-function-type.md +++ b/packages/eslint-plugin/docs/rules/prefer-function-type.md @@ -6,12 +6,10 @@ description: 'Enforce using function types instead of interfaces with call signa > > See **https://typescript-eslint.io/rules/prefer-function-type** for documentation. -## Rule Details +## Examples This rule suggests using a function type instead of an interface or object type literal with a single call signature. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/prefer-includes.md b/packages/eslint-plugin/docs/rules/prefer-includes.md index c06a82d8d642..c927cc7f8294 100644 --- a/packages/eslint-plugin/docs/rules/prefer-includes.md +++ b/packages/eslint-plugin/docs/rules/prefer-includes.md @@ -12,7 +12,7 @@ Until ES2015, we were using `Array#indexOf` method to check whether an array con ES2015 has added `String#includes` and ES2016 has added `Array#includes`. It makes code more understandable if we use those `includes` methods for the purpose. -## Rule Details +## Examples This rule is aimed at suggesting `includes` method if `indexOf` method was used to check whether an object contains an arbitrary value or not. @@ -21,8 +21,6 @@ There are such types: `String`, `Array`, `ReadonlyArray`, and typed arrays. Additionally, this rule reports the tests of simple regular expressions in favor of `String#includes`. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/prefer-literal-enum-member.md b/packages/eslint-plugin/docs/rules/prefer-literal-enum-member.md index 1bb4d23cc08f..071bb49b473f 100644 --- a/packages/eslint-plugin/docs/rules/prefer-literal-enum-member.md +++ b/packages/eslint-plugin/docs/rules/prefer-literal-enum-member.md @@ -23,7 +23,7 @@ enum Foo { The answer is that `Foo.c` will be `1` at runtime. The [playground](https://www.typescriptlang.org/play/#src=const%20imOutside%20%3D%202%3B%0D%0Aconst%20b%20%3D%202%3B%0D%0Aenum%20Foo%20%7B%0D%0A%20%20%20%20outer%20%3D%20imOutside%2C%0D%0A%20%20%20%20a%20%3D%201%2C%0D%0A%20%20%20%20b%20%3D%20a%2C%0D%0A%20%20%20%20c%20%3D%20b%2C%0D%0A%20%20%20%20%2F%2F%20does%20c%20%3D%3D%20Foo.b%20%3D%3D%20Foo.c%20%3D%3D%201%3F%0D%0A%20%20%20%20%2F%2F%20or%20does%20c%20%3D%3D%20b%20%3D%3D%202%3F%0D%0A%7D) illustrates this quite nicely. -## Rule Details +## Examples This rule is meant to prevent unexpected results in code by requiring the use of literal values as enum members to prevent unexpected runtime behavior. Template literals, arrays, objects, constructors, and all other expression types can end up using a variable from its scope or the parent scope, which can result in the same unexpected behavior at runtime. @@ -31,8 +31,6 @@ This rule is meant to prevent unexpected results in code by requiring the use of - `allowBitwiseExpressions` set to `true` will allow you to use bitwise expressions in enum initializer (Default: `false`). -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/prefer-namespace-keyword.md b/packages/eslint-plugin/docs/rules/prefer-namespace-keyword.md index ccb97abbec81..6457045547f0 100644 --- a/packages/eslint-plugin/docs/rules/prefer-namespace-keyword.md +++ b/packages/eslint-plugin/docs/rules/prefer-namespace-keyword.md @@ -9,7 +9,7 @@ description: 'Require using `namespace` keyword over `module` keyword to declare In an effort to prevent further confusion between custom TypeScript modules and the new ES2015 modules, starting with TypeScript `v1.5` the keyword `namespace` is now the preferred way to declare custom TypeScript modules. -## Rule Details +## Examples This rule aims to standardize the way modules are declared. diff --git a/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md b/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md index 272240b4d48e..6aa0c0d4f86e 100644 --- a/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md +++ b/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md @@ -41,7 +41,7 @@ const logical2 = nullString || 'safe'; // logical2 === 'safe' ``` -## Rule Details +## Examples This rule aims enforce the usage of the safer operator. diff --git a/packages/eslint-plugin/docs/rules/prefer-optional-chain.md b/packages/eslint-plugin/docs/rules/prefer-optional-chain.md index a0ff0a0ab224..d4b709bbb890 100644 --- a/packages/eslint-plugin/docs/rules/prefer-optional-chain.md +++ b/packages/eslint-plugin/docs/rules/prefer-optional-chain.md @@ -50,12 +50,10 @@ function myFunc(foo: T | null) { Because the optional chain operator _only_ chains when the property value is `null` or `undefined`, it is much safer than relying upon logical AND operator chaining `&&`; which chains on any _truthy_ value. -## Rule Details +## Examples This rule aims enforce the usage of the safer operator. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/prefer-readonly-parameter-types.md b/packages/eslint-plugin/docs/rules/prefer-readonly-parameter-types.md index 8a281aa38685..644ad742ffa9 100644 --- a/packages/eslint-plugin/docs/rules/prefer-readonly-parameter-types.md +++ b/packages/eslint-plugin/docs/rules/prefer-readonly-parameter-types.md @@ -10,7 +10,7 @@ Mutating function arguments can lead to confusing, hard to debug behavior. Whilst it's easy to implicitly remember to not modify function arguments, explicitly typing arguments as readonly provides clear contract to consumers. This contract makes it easier for a consumer to reason about if a function has side-effects. -## Rule Details +## Examples This rule allows you to enforce that function parameters resolve to readonly types. A type is considered readonly if: @@ -21,8 +21,6 @@ A type is considered readonly if: - it is a readonly tuple type whose elements are all considered readonly. - it is an object type whose properties are all marked as readonly, and whose values are all considered readonly. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/prefer-readonly.md b/packages/eslint-plugin/docs/rules/prefer-readonly.md index c4384e266c3a..016e3e1db95e 100644 --- a/packages/eslint-plugin/docs/rules/prefer-readonly.md +++ b/packages/eslint-plugin/docs/rules/prefer-readonly.md @@ -8,13 +8,11 @@ description: "Require private members to be marked as `readonly` if they're neve This rule enforces that private members are marked as `readonly` if they're never modified outside of the constructor. -## Rule Details +## Examples Member variables with the privacy `private` are never permitted to be modified outside of their declaring class. If that class never modifies their value, they may safely be marked as `readonly`. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/prefer-reduce-type-parameter.md b/packages/eslint-plugin/docs/rules/prefer-reduce-type-parameter.md index d66c91ba9438..e5599cf44ac4 100644 --- a/packages/eslint-plugin/docs/rules/prefer-reduce-type-parameter.md +++ b/packages/eslint-plugin/docs/rules/prefer-reduce-type-parameter.md @@ -18,13 +18,11 @@ solution as casting has subtle effects on the underlying types that can allow bu A better (and lesser known) solution is to pass the type in as a generic parameter to `Array#reduce` explicitly. This means that TypeScript doesn't have to try to infer the type, and avoids the common pitfalls that come with casting. -## Rule Details +## Examples This rule looks for calls to `Array#reduce`, and warns if an initial value is being passed & casted, suggesting instead to pass the cast type to `Array#reduce` as its generic parameter. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/prefer-regexp-exec.md b/packages/eslint-plugin/docs/rules/prefer-regexp-exec.md index 38cae500fa03..aa1cfab63f27 100644 --- a/packages/eslint-plugin/docs/rules/prefer-regexp-exec.md +++ b/packages/eslint-plugin/docs/rules/prefer-regexp-exec.md @@ -8,7 +8,7 @@ description: 'Enforce `RegExp#exec` over `String#match` if no global flag is pro As `String#match` is defined to be the same as `RegExp#exec` when the regular expression does not include the `g` flag, prefer a consistent usage. -## Rule Details +## Examples This rule is aimed at enforcing a consistent way to apply regular expressions to strings. @@ -18,8 +18,6 @@ From [`String#match` on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaSc `RegExp#exec` may also be slightly faster than `String#match`; this is the reason to choose it as the preferred usage. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/prefer-return-this-type.md b/packages/eslint-plugin/docs/rules/prefer-return-this-type.md index 836938ee8921..cc85dbd95b08 100644 --- a/packages/eslint-plugin/docs/rules/prefer-return-this-type.md +++ b/packages/eslint-plugin/docs/rules/prefer-return-this-type.md @@ -49,9 +49,7 @@ const cat = new Cat(); cat.eat().meow(); ``` -## Rule Details - -Examples of code for this rule: +## Examples diff --git a/packages/eslint-plugin/docs/rules/prefer-string-starts-ends-with.md b/packages/eslint-plugin/docs/rules/prefer-string-starts-ends-with.md index 99ead1d79344..e1cd91c584d6 100644 --- a/packages/eslint-plugin/docs/rules/prefer-string-starts-ends-with.md +++ b/packages/eslint-plugin/docs/rules/prefer-string-starts-ends-with.md @@ -9,12 +9,10 @@ description: 'Enforce using `String#startsWith` and `String#endsWith` over other There are multiple ways to verify if a string starts or ends with a specific string, such as `foo.indexOf('bar') === 0`. Since ES2015 has added `String#startsWith` and `String#endsWith`, this rule reports other ways to be consistent. -## Rule Details +## Examples This rule is aimed at enforcing a consistent way to check whether a string starts or ends with a specific string. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/prefer-ts-expect-error.md b/packages/eslint-plugin/docs/rules/prefer-ts-expect-error.md index 85308e4786fb..7fb2188472c8 100644 --- a/packages/eslint-plugin/docs/rules/prefer-ts-expect-error.md +++ b/packages/eslint-plugin/docs/rules/prefer-ts-expect-error.md @@ -16,12 +16,10 @@ To address this, TS3.9 ships with a new single-line comment directive: `// @ts-e This directive operates in the same manner as `@ts-ignore`, but will error if the line it's meant to be suppressing doesn't actually contain an error, making it a lot safer. -## Rule Details +## Examples This rule looks for usages of `@ts-ignore`, and flags them to be replaced with `@ts-expect-error`. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/promise-function-async.md b/packages/eslint-plugin/docs/rules/promise-function-async.md index 3c6b1922cd58..e697217dc5d9 100644 --- a/packages/eslint-plugin/docs/rules/promise-function-async.md +++ b/packages/eslint-plugin/docs/rules/promise-function-async.md @@ -15,7 +15,7 @@ In contrast, non-`async` `Promise` - returning functions are technically capable Code that handles the results of those functions will often need to handle both cases, which can get complex. This rule's practice removes a requirement for creating code to handle both cases. -## Rule Details +## Examples Examples of code for this rule diff --git a/packages/eslint-plugin/docs/rules/quotes.md b/packages/eslint-plugin/docs/rules/quotes.md index 64a5704454cd..b67c5dc8966e 100644 --- a/packages/eslint-plugin/docs/rules/quotes.md +++ b/packages/eslint-plugin/docs/rules/quotes.md @@ -6,7 +6,7 @@ description: 'Enforce the consistent use of either backticks, double, or single > > See **https://typescript-eslint.io/rules/quotes** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/quotes`](https://eslint.org/docs/rules/quotes) rule. It adds support for TypeScript features which allow quoted names, but not backtick quoted names. diff --git a/packages/eslint-plugin/docs/rules/require-array-sort-compare.md b/packages/eslint-plugin/docs/rules/require-array-sort-compare.md index e2e43c811435..ad5ebc20e476 100644 --- a/packages/eslint-plugin/docs/rules/require-array-sort-compare.md +++ b/packages/eslint-plugin/docs/rules/require-array-sort-compare.md @@ -24,12 +24,10 @@ Method calls performed by the `ToString` abstract operations in steps 5 and 7 ha https://www.ecma-international.org/ecma-262/9.0/#sec-sortcompare ::: -## Rule Details +## Examples This rule aims to ensure all calls of the native `Array#sort` method provide a `compareFunction`, while ignoring calls to user-defined `sort` methods. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/require-await.md b/packages/eslint-plugin/docs/rules/require-await.md index a578f0c4b42c..f4ccd6fc21a8 100644 --- a/packages/eslint-plugin/docs/rules/require-await.md +++ b/packages/eslint-plugin/docs/rules/require-await.md @@ -6,7 +6,7 @@ description: 'Disallow async functions which have no `await` expression.' > > See **https://typescript-eslint.io/rules/require-await** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/require-await`](https://eslint.org/docs/rules/require-await) rule. It uses type information to add support for `async` functions that return a `Promise`. diff --git a/packages/eslint-plugin/docs/rules/restrict-plus-operands.md b/packages/eslint-plugin/docs/rules/restrict-plus-operands.md index cf08200be7f5..4969c57b0d18 100644 --- a/packages/eslint-plugin/docs/rules/restrict-plus-operands.md +++ b/packages/eslint-plugin/docs/rules/restrict-plus-operands.md @@ -6,9 +6,7 @@ description: 'Require both operands of addition to have type `number` or `string > > See **https://typescript-eslint.io/rules/restrict-plus-operands** for documentation. -## Rule Details - -Examples of code for this rule: +## Examples diff --git a/packages/eslint-plugin/docs/rules/restrict-template-expressions.md b/packages/eslint-plugin/docs/rules/restrict-template-expressions.md index d22b66dac1de..c3309a559669 100644 --- a/packages/eslint-plugin/docs/rules/restrict-template-expressions.md +++ b/packages/eslint-plugin/docs/rules/restrict-template-expressions.md @@ -6,9 +6,7 @@ description: 'Enforce template literal expressions to be of `string` type.' > > See **https://typescript-eslint.io/rules/restrict-template-expressions** for documentation. -## Rule Details - -Examples of code for this rule: +## Examples diff --git a/packages/eslint-plugin/docs/rules/return-await.md b/packages/eslint-plugin/docs/rules/return-await.md index 13d04d014eb9..205c0eb0e8df 100644 --- a/packages/eslint-plugin/docs/rules/return-await.md +++ b/packages/eslint-plugin/docs/rules/return-await.md @@ -8,7 +8,7 @@ description: 'Enforce consistent returning of awaited values.' Returning an awaited promise can make sense for better stack trace information as well as for consistent error handling (returned promises will not be caught in an async function try/catch). -## Rule Details +## Examples This rule builds on top of the [`eslint/no-return-await`](https://eslint.org/docs/rules/no-return-await) rule. It expands upon the base rule to add support for optionally requiring `return await` in certain cases. diff --git a/packages/eslint-plugin/docs/rules/semi.md b/packages/eslint-plugin/docs/rules/semi.md index ee33eca92236..16622a1d856f 100644 --- a/packages/eslint-plugin/docs/rules/semi.md +++ b/packages/eslint-plugin/docs/rules/semi.md @@ -8,7 +8,7 @@ description: 'Require or disallow semicolons instead of ASI.' This rule enforces consistent use of semicolons after statements. -## Rule Details +## Examples This rule extends the base [`eslint/semi`](https://eslint.org/docs/rules/semi) rule. It adds support for TypeScript features that require semicolons. diff --git a/packages/eslint-plugin/docs/rules/sort-type-union-intersection-members.md b/packages/eslint-plugin/docs/rules/sort-type-union-intersection-members.md index 68b5fce8aca2..ae85e0c98065 100644 --- a/packages/eslint-plugin/docs/rules/sort-type-union-intersection-members.md +++ b/packages/eslint-plugin/docs/rules/sort-type-union-intersection-members.md @@ -12,7 +12,7 @@ Sorting union (`|`) and intersection (`&`) types can help: - find repeated types - reduce diff churn -## Rule Details +## Examples Sorting within each group is done using the following code: @@ -29,8 +29,6 @@ function compare(a, b) { In other words, the types are sorted alphabetically, case-insensitively and treating numbers like a human would, falling back to character code sorting in case of ties. -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/space-before-blocks.md b/packages/eslint-plugin/docs/rules/space-before-blocks.md index daba57a2ec21..716de2294f6b 100644 --- a/packages/eslint-plugin/docs/rules/space-before-blocks.md +++ b/packages/eslint-plugin/docs/rules/space-before-blocks.md @@ -6,7 +6,7 @@ description: 'Enforce consistent spacing before blocks.' > > See **https://typescript-eslint.io/rules/space-before-blocks** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/space-before-blocks`](https://eslint.org/docs/rules/space-before-blocks) rule. It adds support for interfaces and enums. diff --git a/packages/eslint-plugin/docs/rules/space-before-function-paren.md b/packages/eslint-plugin/docs/rules/space-before-function-paren.md index 5760b5128d10..f2c1b5e846c2 100644 --- a/packages/eslint-plugin/docs/rules/space-before-function-paren.md +++ b/packages/eslint-plugin/docs/rules/space-before-function-paren.md @@ -6,7 +6,7 @@ description: 'Enforce consistent spacing before function parenthesis.' > > See **https://typescript-eslint.io/rules/space-before-function-paren** for documentation. -## Rule Details +## Examples This rule extends the base [`eslint/space-before-function-paren`](https://eslint.org/docs/rules/space-before-function-paren) rule. It adds support for generic type parameters on function calls. diff --git a/packages/eslint-plugin/docs/rules/strict-boolean-expressions.md b/packages/eslint-plugin/docs/rules/strict-boolean-expressions.md index f25aa3efc1d3..b7e8c13a9be2 100644 --- a/packages/eslint-plugin/docs/rules/strict-boolean-expressions.md +++ b/packages/eslint-plugin/docs/rules/strict-boolean-expressions.md @@ -21,8 +21,6 @@ The following nodes are considered boolean expressions and their type is checked ## Examples -Examples of code for this rule: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/switch-exhaustiveness-check.md b/packages/eslint-plugin/docs/rules/switch-exhaustiveness-check.md index 4cc7e152e7ad..a3300d406021 100644 --- a/packages/eslint-plugin/docs/rules/switch-exhaustiveness-check.md +++ b/packages/eslint-plugin/docs/rules/switch-exhaustiveness-check.md @@ -8,9 +8,7 @@ description: 'Require switch-case statements to be exhaustive with union type.' Union type may have a lot of parts. It's easy to forget to consider all cases in switch. This rule reminds which parts are missing. If domain of the problem requires to have only a partial switch, developer may _explicitly_ add a default clause. -## Rule Details - -Examples of code for this rule: +## Examples diff --git a/packages/eslint-plugin/docs/rules/triple-slash-reference.md b/packages/eslint-plugin/docs/rules/triple-slash-reference.md index 75edec3261a2..c9bd861a4362 100644 --- a/packages/eslint-plugin/docs/rules/triple-slash-reference.md +++ b/packages/eslint-plugin/docs/rules/triple-slash-reference.md @@ -6,7 +6,7 @@ description: 'Disallow certain triple slash directives in favor of ES6-style imp > > See **https://typescript-eslint.io/rules/triple-slash-reference** for documentation. -## Rule Details +## Examples Use of triple-slash reference type directives is discouraged in favor of the newer `import` style. This rule allows you to ban use of `/// `, `/// `, or `/// ` directives. diff --git a/packages/eslint-plugin/docs/rules/type-annotation-spacing.md b/packages/eslint-plugin/docs/rules/type-annotation-spacing.md index d3a97920072f..36cfab06592f 100644 --- a/packages/eslint-plugin/docs/rules/type-annotation-spacing.md +++ b/packages/eslint-plugin/docs/rules/type-annotation-spacing.md @@ -35,7 +35,7 @@ type Foo = (string: name)=> string; type Foo = (string: name) =>string; ``` -## Rule Details +## Examples This rule aims to enforce specific spacing patterns around type annotations and function types in type literals. diff --git a/packages/eslint-plugin/docs/rules/typedef.md b/packages/eslint-plugin/docs/rules/typedef.md index 317f96879578..3e1e2f6459ec 100644 --- a/packages/eslint-plugin/docs/rules/typedef.md +++ b/packages/eslint-plugin/docs/rules/typedef.md @@ -31,7 +31,7 @@ TypeScript is often better at inferring types than easily written type annotatio ::: -## Rule Details +## Examples This rule can enforce type annotations in locations regardless of whether they're required. This is typically used to maintain consistency for element types that sometimes require them. diff --git a/packages/eslint-plugin/docs/rules/unbound-method.md b/packages/eslint-plugin/docs/rules/unbound-method.md index fe030ad5facc..091780dcb6c4 100644 --- a/packages/eslint-plugin/docs/rules/unbound-method.md +++ b/packages/eslint-plugin/docs/rules/unbound-method.md @@ -11,7 +11,7 @@ If your function does not access `this`, [you can annotate it with `this: void`] If you're working with `jest`, you can use [`eslint-plugin-jest`'s version of this rule](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/unbound-method.md) to lint your test files, which knows when it's ok to pass an unbound method to `expect` calls. -## Rule Details +## Examples Examples of code for this rule with the default options: diff --git a/packages/eslint-plugin/docs/rules/unified-signatures.md b/packages/eslint-plugin/docs/rules/unified-signatures.md index ad6bbb917aa3..b4b178d3df3e 100644 --- a/packages/eslint-plugin/docs/rules/unified-signatures.md +++ b/packages/eslint-plugin/docs/rules/unified-signatures.md @@ -6,7 +6,7 @@ description: 'Disallow two overloads that could be unified into one with a union > > See **https://typescript-eslint.io/rules/unified-signatures** for documentation. -## Rule Details +## Examples This rule aims to keep the source code as maintainable as possible by reducing the amount of overloads. diff --git a/packages/eslint-plugin/src/rules/ban-ts-comment.ts b/packages/eslint-plugin/src/rules/ban-ts-comment.ts index d9e3659ce0ae..9c55b437da63 100644 --- a/packages/eslint-plugin/src/rules/ban-ts-comment.ts +++ b/packages/eslint-plugin/src/rules/ban-ts-comment.ts @@ -28,7 +28,7 @@ export default util.createRule<[Options], MessageIds>({ type: 'problem', docs: { description: - 'Disallow `@ts-` comments or require descriptions after directive', + 'Disallow `@ts-` comments or require descriptions after directives', recommended: 'error', }, messages: { diff --git a/packages/eslint-plugin/src/rules/no-extra-non-null-assertion.ts b/packages/eslint-plugin/src/rules/no-extra-non-null-assertion.ts index 8d15029f7162..a69cd262d6e3 100644 --- a/packages/eslint-plugin/src/rules/no-extra-non-null-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-extra-non-null-assertion.ts @@ -7,7 +7,7 @@ export default util.createRule({ meta: { type: 'problem', docs: { - description: 'Disallow extra non-null assertion', + description: 'Disallow extra non-null assertions', recommended: 'error', }, fixable: 'code', diff --git a/packages/website/plugins/generated-rule-docs.ts b/packages/website/plugins/generated-rule-docs.ts index e21a408dbf42..020ac5f74a82 100644 --- a/packages/website/plugins/generated-rule-docs.ts +++ b/packages/website/plugins/generated-rule-docs.ts @@ -210,7 +210,7 @@ export const generatedRuleDocs: Plugin = () => { };`, } as mdast.Code); } else { - root.children.splice(optionsH2Index, 0, { + root.children.splice(attributesH2Index + 1, 0, { lang: 'js', type: 'code', meta: 'title=".eslintrc.cjs"', diff --git a/packages/website/sidebars/sidebar.rules.js b/packages/website/sidebars/sidebar.rules.js index b5fd6ce147d5..e698d7cda05c 100644 --- a/packages/website/sidebars/sidebar.rules.js +++ b/packages/website/sidebars/sidebar.rules.js @@ -68,26 +68,17 @@ module.exports = { someSidebar: [ 'README', { - ...createCategory( - 'Rules', - [], - [ - { - ...createCategory('TypeScript Rules', Array.from(typescriptRules)), - collapsed: false, - }, - { - ...createCategory('Extension Rules', Array.from(extensionRules)), - collapsed: false, - }, - createCategory('Formatting Rules', Array.from(formattingRules)), - createCategory('Deprecated Rules', [ - ...Array.from(deprecatedRules), - ...paths, - ]), - ], - ), - collapsible: false, + ...createCategory('TypeScript Rules', Array.from(typescriptRules)), + collapsed: false, }, + { + ...createCategory('Extension Rules', Array.from(extensionRules)), + collapsed: false, + }, + createCategory('Formatting Rules', Array.from(formattingRules)), + createCategory('Deprecated Rules', [ + ...Array.from(deprecatedRules), + ...paths, + ]), ], }; diff --git a/packages/website/src/theme/MDXComponents/Feature.module.css b/packages/website/src/theme/MDXComponents/Feature.module.css new file mode 100644 index 000000000000..ac65c0a1d977 --- /dev/null +++ b/packages/website/src/theme/MDXComponents/Feature.module.css @@ -0,0 +1,23 @@ +.feature { + background-color: var(--token-background); + border-radius: var(--ifm-code-border-radius); + box-shadow: var(--ifm-global-shadow-lw); + color: var(--token-color) !important; + display: flex; + font-size: 0.8rem; + margin: 0 0 1rem; + padding: 0.75rem 1rem; + width: 100%; +} + +.emoji { + margin-right: 0.5rem; +} + +.children { + margin: 0; +} + +.feature + .feature { + margin-left: 1rem; +} diff --git a/packages/website/src/theme/MDXComponents/Feature.tsx b/packages/website/src/theme/MDXComponents/Feature.tsx new file mode 100644 index 000000000000..157f0949a31c --- /dev/null +++ b/packages/website/src/theme/MDXComponents/Feature.tsx @@ -0,0 +1,23 @@ +import clsx from 'clsx'; +import React from 'react'; + +import styles from './Feature.module.css'; + +export interface FeatureProps { + children: React.ReactNode; + emoji: string; + fullWidth?: boolean; +} + +export function Feature({ + children, + emoji, + fullWidth, +}: FeatureProps): JSX.Element { + return ( +
    +
    {emoji}
    +

    {children}

    +
    + ); +} diff --git a/packages/website/src/theme/MDXComponents/RuleAttributes.module.css b/packages/website/src/theme/MDXComponents/RuleAttributes.module.css index 97c07287baba..87c45721e1d3 100644 --- a/packages/website/src/theme/MDXComponents/RuleAttributes.module.css +++ b/packages/website/src/theme/MDXComponents/RuleAttributes.module.css @@ -1,7 +1,3 @@ -.taskList { - list-style: none; -} - -:not(.taskList > li) > .taskList { - padding-left: 0; +.features { + display: flex; } diff --git a/packages/website/src/theme/MDXComponents/RuleAttributes.tsx b/packages/website/src/theme/MDXComponents/RuleAttributes.tsx index 1b1ea96278d6..bd98fbcb4272 100644 --- a/packages/website/src/theme/MDXComponents/RuleAttributes.tsx +++ b/packages/website/src/theme/MDXComponents/RuleAttributes.tsx @@ -1,57 +1,96 @@ +import type { RuleMetaDataDocs } from '@site/../utils/dist/ts-eslint/Rule'; import { useRulesMeta } from '@site/src/hooks/useRulesMeta'; import React from 'react'; +import type { FeatureProps } from './Feature'; +import { Feature } from './Feature'; import styles from './RuleAttributes.module.css'; -const recommendations = { - error: '✅ recommended', - warn: '✅ recommended', - strict: '🔒 Strict', - false: 'none', +const getRecommendation = (docs: RuleMetaDataDocs): [string, string] => { + return docs.recommended === 'strict' + ? ['🔒', 'strict'] + : docs.requiresTypeChecking + ? ['🧠', 'recommended-requiring-type-checking'] + : ['✅', 'recommended']; }; -export function RuleAttributes({ name }: { name: string }): JSX.Element | null { +export function RuleAttributes({ name }: { name: string }): React.ReactNode { const rules = useRulesMeta(); const rule = rules.find(rule => rule.name === name); if (!rule?.docs) { return null; } + const features: FeatureProps[] = []; + + if (rule.docs.recommended) { + const [emoji, recommendation] = getRecommendation(rule.docs); + features.push({ + children: ( + <> + Extend{' '} + + "plugin:@typescript-eslint/{recommendation}" + {' '} + in an{' '} + + ESLint configuration file + {' '} + to enable this rule. + + ), + emoji, + }); + } + + if (rule.fixable) { + features.push({ + children: ( + <> + Some problems reported by this rule are automatically fixable by the{' '} + --fix{' '} + + ESLint command line option + + . + + ), + emoji: '🛠', + }); + } + + if (rule.hasSuggestions) { + features.push({ + children: ( + <> + Some problems reported by this rule are manually fixable by editor{' '} + + suggestions + + . + + ), + emoji: '💡', + }); + } + + if (rule.docs.requiresTypeChecking) { + features.push({ + children: ( + <> + This rule requires{' '} + type information to run. + + ), + emoji: '💭', + }); + } + return ( - <> -

    Attributes

    -
      -
    • - - Included in config: {recommendations[`${rule.docs.recommended}`]} -
    • -
    • - - Fixable -
        -
      • - - 🔧 Automated Fixer -
      • -
      • - - 💡 Suggestion Fixer -
      • -
      -
    • -
    • - - 💭 Requires type information -
    • -
    - +
    + {features.map(feature => ( + + ))} +
    ); } From 4d77ebc755b1d3b5fc97989cc4be99299c353ace Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 1 Oct 2022 00:56:16 -0400 Subject: [PATCH 04/14] progress --- .../docs/rules/member-delimiter-style.md | 47 +----- .../docs/rules/no-base-to-string.md | 17 ++- .../docs/rules/no-explicit-any.md | 11 +- .../docs/rules/no-floating-promises.md | 2 +- .../docs/rules/no-for-in-array.md | 42 +++-- .../docs/rules/no-inferrable-types.md | 53 ++----- .../docs/rules/no-invalid-void-type.md | 15 +- .../rules/no-meaningless-void-operator.md | 27 +--- .../docs/rules/no-misused-new.md | 17 ++- .../docs/rules/no-misused-promises.md | 144 +++++++----------- .../eslint-plugin/docs/rules/no-namespace.md | 11 +- ...no-non-null-asserted-nullish-coalescing.md | 14 +- .../no-non-null-asserted-optional-chain.md | 31 +--- .../docs/rules/no-non-null-assertion.md | 25 +-- .../rules/no-redundant-type-constituents.md | 7 +- .../docs/rules/no-require-imports.md | 23 ++- .../eslint-plugin/docs/rules/no-this-alias.md | 22 +-- .../no-unnecessary-boolean-literal-compare.md | 27 ++-- .../docs/rules/no-unnecessary-condition.md | 3 +- .../docs/rules/no-unnecessary-qualifier.md | 56 ++----- .../rules/no-unnecessary-type-arguments.md | 30 +++- .../rules/no-unnecessary-type-assertion.md | 6 +- .../rules/no-unnecessary-type-constraint.md | 24 +-- .../docs/rules/no-unsafe-argument.md | 17 ++- .../docs/rules/no-unsafe-assignment.md | 15 +- .../docs/rules/no-unsafe-call.md | 9 +- .../docs/rules/no-unsafe-member-access.md | 9 +- .../docs/rules/no-unsafe-return.md | 15 +- .../docs/rules/no-useless-empty-export.md | 8 +- .../docs/rules/no-var-requires.md | 6 +- .../non-nullable-type-assertion-style.md | 8 +- .../docs/rules/parameter-properties.md | 9 +- .../docs/rules/prefer-as-const.md | 8 +- .../docs/rules/prefer-enum-initializers.md | 26 +--- .../eslint-plugin/docs/rules/prefer-for-of.md | 27 ++-- .../docs/rules/prefer-function-type.md | 44 +++--- .../docs/rules/prefer-includes.md | 56 +++---- .../docs/rules/prefer-literal-enum-member.md | 19 +-- .../docs/rules/prefer-namespace-keyword.md | 29 +++- .../docs/rules/prefer-nullish-coalescing.md | 58 +------ .../docs/rules/prefer-optional-chain.md | 56 ++----- .../rules/prefer-readonly-parameter-types.md | 4 +- .../docs/rules/prefer-readonly.md | 8 +- .../rules/prefer-reduce-type-parameter.md | 12 +- .../docs/rules/prefer-regexp-exec.md | 15 +- .../docs/rules/prefer-return-this-type.md | 31 ++-- .../rules/prefer-string-starts-ends-with.md | 14 +- .../docs/rules/prefer-ts-expect-error.md | 12 +- .../docs/rules/require-array-sort-compare.md | 15 +- .../docs/rules/restrict-plus-operands.md | 20 ++- .../rules/restrict-template-expressions.md | 9 ++ .../sort-type-union-intersection-members.md | 17 +-- .../docs/rules/switch-exhaustiveness-check.md | 37 ++--- .../docs/rules/triple-slash-reference.md | 6 +- packages/eslint-plugin/docs/rules/typedef.md | 12 +- .../docs/rules/unbound-method.md | 9 +- .../docs/rules/unified-signatures.md | 8 +- .../eslint-plugin/src/rules/no-namespace.ts | 4 +- .../src/rules/restrict-plus-operands.ts | 2 +- .../website/plugins/generated-rule-docs.ts | 61 ++++---- .../theme/MDXComponents/Feature.module.css | 9 +- .../src/theme/MDXComponents/Feature.tsx | 10 +- .../MDXComponents/RuleAttributes.module.css | 6 + .../theme/MDXComponents/RuleAttributes.tsx | 37 +++-- 64 files changed, 625 insertions(+), 806 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/member-delimiter-style.md b/packages/eslint-plugin/docs/rules/member-delimiter-style.md index dae4f51f6296..d2e1f59ec4fc 100644 --- a/packages/eslint-plugin/docs/rules/member-delimiter-style.md +++ b/packages/eslint-plugin/docs/rules/member-delimiter-style.md @@ -6,59 +6,26 @@ description: 'Require a specific member delimiter style for interfaces and type > > See **https://typescript-eslint.io/rules/member-delimiter-style** for documentation. -Enforces a consistent member delimiter style in interfaces and type literals. There are three member delimiter styles primarily used in TypeScript: - -- Semicolon style (default, preferred in TypeScript). +TypeScript allows three delimiters between members in interfaces and type aliases: ```ts interface Foo { + // Semicolons (default, preferred in TypeScript): name: string; - greet(): void; -} - -type Bar = { - name: string; - greet(): void; -} -``` -- Comma style (JSON style). - - -```ts -interface Foo { + // Commas (JSON-like): name: string, - greet(): void, -} -type Bar = { - name: string, - greet(): void, -} -``` - -- Line break (none) style. - - -```ts -interface Foo { + // Line breaks (none): name: string - greet(): void -} - -type Bar = { - name: string - greet(): void } ``` -The rule also enforces the presence (or absence) of the delimiter in the last member of the interface and/or type literal. -Finally, this rule can enforce separate delimiter syntax for single line declarations. - -## Examples +For code readability, it's generally best to use the same style consistently in your codebase. -This rule aims to standardize the way interface and type literal members are delimited. +This rule enforces keeping to one configurable code style. +It can also standardize the presence (or absence) of a delimiter in the last member of a construct, as well as a separate delimiter syntax for single line declarations. ## Options diff --git a/packages/eslint-plugin/docs/rules/no-base-to-string.md b/packages/eslint-plugin/docs/rules/no-base-to-string.md index 453968828ce3..7409f5e134e2 100644 --- a/packages/eslint-plugin/docs/rules/no-base-to-string.md +++ b/packages/eslint-plugin/docs/rules/no-base-to-string.md @@ -8,17 +8,13 @@ description: 'Require `.toString()` to only be called on objects which provide u JavaScript will call `toString()` on an object when it is converted to a string, such as when `+` adding to a string or in `${}` template literals. The default Object `.toString()` returns `"[object Object]"`, which is often not what was intended. -This rule requires stringified objects define a more useful `.toString()` method. - -> This rule has some overlap with [`restrict-plus-operands`](./restrict-plus-operands.md) and [`restrict-template-expressions`](./restrict-template-expressions.md). - -## Examples - -This rule prevents accidentally defaulting to the base Object `.toString()` method. +This rule reports on stringified values that aren't primitives and don't define a more useful `.toString()` method. > Note that `Function` provides its own `.toString()` that returns the function's code. > Functions are not flagged by this rule. +## Examples + ### ❌ Incorrect @@ -82,4 +78,11 @@ let text = `${value}`; If you don't mind `"[object Object]"` in your strings, then you will not need this rule. +## Related To + +- [`restrict-plus-operands`](./restrict-plus-operands.md) +- [`restrict-template-expressions`](./restrict-template-expressions.md) + +## Further Reading + - [`Object.prototype.toString()` MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString) diff --git a/packages/eslint-plugin/docs/rules/no-explicit-any.md b/packages/eslint-plugin/docs/rules/no-explicit-any.md index c2701453aca5..efec50113734 100644 --- a/packages/eslint-plugin/docs/rules/no-explicit-any.md +++ b/packages/eslint-plugin/docs/rules/no-explicit-any.md @@ -7,7 +7,8 @@ description: 'Disallow the `any` type.' > See **https://typescript-eslint.io/rules/no-explicit-any** for documentation. The `any` type in TypeScript is a dangerous "escape hatch" from the type system. -Using `any` disables many type checking rules and is generally considered only valid in rare edge cases or when prototyping code. +Using `any` disables many type checking rules and is generally best used only as a last resort or when prototyping code. +This rule reports on explicit uses of the `any` keyword as a type annotation. > TypeScript's `--noImplicitAny` compiler option prevents an implied `any`, but doesn't prevent `any` from being explicitly used the way this rule does. @@ -160,6 +161,14 @@ interface Garply { If an unknown type or a library without typings is used and you want to be able to specify `any`. +## Related To + +- [`no-unsafe-argument`](./no-unsafe-argument.md) +- [`no-unsafe-assignment`](./no-unsafe-assignment.md) +- [`no-unsafe-call`](./no-unsafe-call.md) +- [`no-unsafe-member-access`](./no-unsafe-member-access.md) +- [`no-unsafe-return`](./no-unsafe-return.md) + ## Further Reading - TypeScript [any type](https://www.typescriptlang.org/docs/handbook/basic-types.html#any) diff --git a/packages/eslint-plugin/docs/rules/no-floating-promises.md b/packages/eslint-plugin/docs/rules/no-floating-promises.md index 0e19e3642bf4..289e42f903c5 100644 --- a/packages/eslint-plugin/docs/rules/no-floating-promises.md +++ b/packages/eslint-plugin/docs/rules/no-floating-promises.md @@ -7,9 +7,9 @@ description: 'Require Promise-like statements to be handled appropriately.' > See **https://typescript-eslint.io/rules/no-floating-promises** for documentation. A "floating" Promise is one that is created without any code set up to handle any errors it might throw. - Floating Promises can cause several issues, such as improperly sequenced operations, ignored Promise rejections, and more. +This rule reports when a Promise is created and not properly handled. Valid ways of handling a Promise-valued statement include: - `await`ing it diff --git a/packages/eslint-plugin/docs/rules/no-for-in-array.md b/packages/eslint-plugin/docs/rules/no-for-in-array.md index 9cf2ca3f54ae..759f427b9ace 100644 --- a/packages/eslint-plugin/docs/rules/no-for-in-array.md +++ b/packages/eslint-plugin/docs/rules/no-for-in-array.md @@ -6,38 +6,48 @@ description: 'Disallow iterating over an array with a for-in loop.' > > See **https://typescript-eslint.io/rules/no-for-in-array** for documentation. -This rule prohibits iterating over an array with a for-in loop. - -## Examples - -A for-in loop (`for (var k in o)`) iterates over the properties of an Object. +A for-in loop (`for (var i in o)`) iterates over the properties of an Object. While it is legal to use for-in loops with array types, it is not common. for-in will iterate over the indices of the array as strings, omitting any "holes" in the array. -More common is to use for-of, which iterates over the values of an array. -If you want to iterate over the indices, alternatives include: -```js -array.forEach((value, index) => { ... }); -for (const [index, value] of array.entries()) { ... } -for (let i = 0; i < array.length; i++) { ... } -``` +## Examples ### ❌ Incorrect ```js -for (const x in [3, 4, 5]) { - console.log(x); +declare const array: string[]; + +for (const i in array) { + console.log(array[i]); +} + +for (const i in array) { + console.log(i, array[i]); } ``` ### ✅ Correct ```js -for (const x in { a: 3, b: 4, c: 5 }) { - console.log(x); +declare const array: string[]; + +for (const value of array) { + console.log(value); +} + +for (let i = 0; i < array.length; i += 1) { + console.log(i, array[i]); +} + +array.forEach((value, i) => { + console.log(i, value); +}) + +for (const [i, value] of array.entries()) { + console.log(i, value); } ``` diff --git a/packages/eslint-plugin/docs/rules/no-inferrable-types.md b/packages/eslint-plugin/docs/rules/no-inferrable-types.md index b26ceb62908a..0427bf8acad6 100644 --- a/packages/eslint-plugin/docs/rules/no-inferrable-types.md +++ b/packages/eslint-plugin/docs/rules/no-inferrable-types.md @@ -6,45 +6,29 @@ description: 'Disallow explicit type declarations for variables or parameters in > > See **https://typescript-eslint.io/rules/no-inferrable-types** for documentation. -Explicit types where they can be easily inferred may add unnecessary verbosity. +TypeScript is able to infer the types of parameters, properties, and variables from their default or initial values. +There is no need to use an explicit `:` type annotation on one of those constructs initialized to a boolean, number, or string. +Doing so adds unnecessary verbosity to code -making it harder to read- and in some cases can prevent TypeScript from inferring a more specific literal type (e.g. `10`) instead of the more general primitive type (e.g. `number`) ## Examples -This rule disallows explicit type declarations on parameters, variables -and properties where the type can be easily inferred from its value. - -Examples of code with the default options: - ### ❌ Incorrect ```ts const a: bigint = 10n; -const a: bigint = -10n; const a: bigint = BigInt(10); -const a: bigint = -BigInt(10); -const a: boolean = false; -const a: boolean = true; -const a: boolean = Boolean(null); const a: boolean = !0; +const a: boolean = Boolean(null); +const a: boolean = true; +const a: null = null; const a: number = 10; -const a: number = +10; -const a: number = -10; -const a: number = Number('1'); -const a: number = +Number('1'); -const a: number = -Number('1'); const a: number = Infinity; -const a: number = +Infinity; -const a: number = -Infinity; const a: number = NaN; -const a: number = +NaN; -const a: number = -NaN; -const a: null = null; +const a: number = Number('1'); const a: RegExp = /a/; -const a: RegExp = RegExp('a'); const a: RegExp = new RegExp('a'); -const a: string = 'str'; const a: string = `str`; const a: string = String(1); const a: symbol = Symbol('a'); @@ -62,30 +46,17 @@ function fn(a: number = 5, b: boolean = true) {} ```ts const a = 10n; -const a = -10n; const a = BigInt(10); -const a = -BigInt(10); -const a = false; -const a = true; -const a = Boolean(null); const a = !0; +const a = Boolean(null); +const a = true; +const a = null; const a = 10; -const a = +10; -const a = -10; -const a = Number('1'); -const a = +Number('1'); -const a = -Number('1'); const a = Infinity; -const a = +Infinity; -const a = -Infinity; const a = NaN; -const a = +NaN; -const a = -NaN; -const a = null; +const a = Number('1'); const a = /a/; -const a = RegExp('a'); const a = new RegExp('a'); -const a = 'str'; const a = `str`; const a = String(1); const a = Symbol('a'); @@ -97,8 +68,6 @@ class Foo { } function fn(a = 5, b = true) {} - -function fn(a: number, b: boolean, c: string) {} ``` diff --git a/packages/eslint-plugin/docs/rules/no-invalid-void-type.md b/packages/eslint-plugin/docs/rules/no-invalid-void-type.md index 14403638ac9c..d2b60d59e68f 100644 --- a/packages/eslint-plugin/docs/rules/no-invalid-void-type.md +++ b/packages/eslint-plugin/docs/rules/no-invalid-void-type.md @@ -6,20 +6,15 @@ description: 'Disallow `void` type outside of generic or return types.' > > See **https://typescript-eslint.io/rules/no-invalid-void-type** for documentation. -Disallows usage of `void` type outside of return types or generic type arguments. -If `void` is used as return type, it shouldn’t be a part of intersection/union type with most other types. +`void` in TypeScript refers to a function return that is meant to be ignored. +Attempting to use a `void` type outside of a return type or generic type argument is often a sign of programmer error. +`void` can also be misleading for other developers even if used correctly. -## Rationale - -The `void` type means “nothing” or that a function does not return any value, -in contrast with implicit `undefined` type which means that a function returns a value `undefined`. -So “nothing” cannot be mixed with any other types, other than `never`, which accepts all types. -If you need this - use the `undefined` type instead. +> The `void` type means cannot be mixed with any other types, other than `never`, which accepts all types. +> If you think you need this then you probably want the `undefined` type instead. ## Examples -This rule aims to ensure that the `void` type is only used in valid places. - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.md b/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.md index 1563f3b69b28..f904c473d667 100644 --- a/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.md +++ b/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.md @@ -6,13 +6,15 @@ description: 'Disallow the `void` operator except when used to discard a value.' > > See **https://typescript-eslint.io/rules/no-meaningless-void-operator** for documentation. -Disallows the `void` operator when its argument is already of type `void` or `undefined`. +`void` in TypeScript refers to a function return that is meant to be ignored. +The `void` operator is a useful tool to convey the programmer's intent to discard a value. +For example, it is recommended as one way of suppressing [`@typescript-eslint/no-floating-promises`](./no-floating-promises.md) instead of adding `.catch()` to a promise. -## Examples - -The `void` operator is a useful tool to convey the programmer's intent to discard a value. For example, it is recommended as one way of suppressing [`@typescript-eslint/no-floating-promises`](./no-floating-promises.md) instead of adding `.catch()` to a promise. +This rule helps an authors catch API changes where previously a value was being discarded at a call site, but the callee changed so it no longer returns a value. +When combined with [no-unused-expressions](https://eslint.org/docs/rules/no-unused-expressions), it also helps _readers_ of the code by ensuring consistency: a statement that looks like `void foo();` is **always** discarding a return value, and a statement that looks like `foo();` is **never** discarding a return value. +This rule reports on any `void` operator whose argument is already of type `void` or `undefined`. -This rule helps an author catch API changes where previously a value was being discarded at a call site, but the callee changed so it no longer returns a value. When combined with [no-unused-expressions](https://eslint.org/docs/rules/no-unused-expressions), it also helps _readers_ of the code by ensuring consistency: a statement that looks like `void foo();` is **always** discarding a return value, and a statement that looks like `foo();` is **never** discarding a return value. +## Examples @@ -42,17 +44,4 @@ void bar(); // discarding a number ## Options -This rule accepts a single object option with the following default configuration: - -```json -{ - "@typescript-eslint/no-meaningless-void-operator": [ - "error", - { - "checkNever": false - } - ] -} -``` - -- `checkNever: true` will suggest removing `void` when the argument has type `never`. +`checkNever: true` will suggest removing `void` when the argument has type `never`. diff --git a/packages/eslint-plugin/docs/rules/no-misused-new.md b/packages/eslint-plugin/docs/rules/no-misused-new.md index 45e8e5723cb7..a311c40be7a0 100644 --- a/packages/eslint-plugin/docs/rules/no-misused-new.md +++ b/packages/eslint-plugin/docs/rules/no-misused-new.md @@ -6,7 +6,11 @@ description: 'Enforce valid definition of `new` and `constructor`.' > > See **https://typescript-eslint.io/rules/no-misused-new** for documentation. -Warns on apparent attempts to define constructors for interfaces or `new` for classes. +JavaScript classes may define a `constructor` method that runs when a class instance is newly created. +TypeScript allows interfaces that describe a static class object to define a `new()` method (though this is rarely used in real world code). +Developers new to JavaScript classes and/or TypeScript interfaces may sometimes confuse when to use `constructor` or `new`. + +This rule reports when a class defines a method named `new` or an interface defines a method named `constructor`. ## Examples @@ -15,7 +19,7 @@ Warns on apparent attempts to define constructors for interfaces or `new` for cl ### ❌ Incorrect ```ts -class C { +declare class C { new(): C; } @@ -28,10 +32,15 @@ interface I { ### ✅ Correct ```ts -class C { - constructor() {} +declare class C { + constructor(); } + interface I { new (): C; } ``` + +## When Not To Use It + +If you intentionally want a class with a `new` method, and you're confident nobody working in your code will mistake it with a constructor. diff --git a/packages/eslint-plugin/docs/rules/no-misused-promises.md b/packages/eslint-plugin/docs/rules/no-misused-promises.md index 2b2f512a1c1b..72d4e5c670bf 100644 --- a/packages/eslint-plugin/docs/rules/no-misused-promises.md +++ b/packages/eslint-plugin/docs/rules/no-misused-promises.md @@ -15,40 +15,8 @@ functions are handled/awaited. See [`no-floating-promises`](./no-floating-promises.md) for detecting unhandled Promise _statements_. ::: -## Examples - -This rule accepts a single option which is an object with `checksConditionals`, -`checksVoidReturn`, and `checksSpreads` properties indicating which types of -misuse to flag. All are enabled by default. - ## Options -```ts -type Options = [ - { - checksConditionals?: boolean; - checksVoidReturn?: boolean | ChecksVoidReturnOptions; - checksSpreads?: boolean; - }, -]; - -interface ChecksVoidReturnOptions { - arguments?: boolean; - attributes?: boolean; - properties?: boolean; - returns?: boolean; - variables?: boolean; -} - -const defaultOptions: Options = [ - { - checksConditionals: true, - checksVoidReturn: true, - checksSpreads: true, - }, -]; -``` - ### `"checksConditionals"` If you don't want to check conditionals, you can configure the rule with `"checksConditionals": false`: @@ -66,6 +34,45 @@ If you don't want to check conditionals, you can configure the rule with `"check Doing so prevents the rule from looking at code like `if (somePromise)`. +Examples of code for this rule with `checksConditionals: true`: + + + +#### ❌ Incorrect + +```ts +const promise = Promise.resolve('value'); + +if (promise) { + // Do something +} + +const val = promise ? 123 : 456; + +while (promise) { + // Do something +} +``` + +#### ✅ Correct + +```ts +const promise = Promise.resolve('value'); + +// Always `await` the Promise in a conditional +if (await promise) { + // Do something +} + +const val = (await promise) ? 123 : 456; + +while (await promise) { + // Do something +} +``` + + + ### `"checksVoidReturn"` Likewise, if you don't want functions that return promises where a void return is @@ -107,64 +114,6 @@ For example, if you don't mind that passing a `() => Promise` to a `() => } ``` -### `"checksSpreads"` - -If you don't want to check object spreads, you can add this configuration: - -```json -{ - "@typescript-eslint/no-misused-promises": [ - "error", - { - "checksSpreads": false - } - ] -} -``` - -### `checksConditionals: true` - -Examples of code for this rule with `checksConditionals: true`: - - - -#### ❌ Incorrect - -```ts -const promise = Promise.resolve('value'); - -if (promise) { - // Do something -} - -const val = promise ? 123 : 456; - -while (promise) { - // Do something -} -``` - -#### ✅ Correct - -```ts -const promise = Promise.resolve('value'); - -// Always `await` the Promise in a conditional -if (await promise) { - // Do something -} - -const val = (await promise) ? 123 : 456; - -while (await promise) { - // Do something -} -``` - - - -### `checksVoidReturn: true` - Examples of code for this rule with `checksVoidReturn: true`: @@ -233,7 +182,20 @@ eventEmitter.on('some-event', () => { -### `checksSpreads: true` +### `"checksSpreads"` + +If you don't want to check object spreads, you can add this configuration: + +```json +{ + "@typescript-eslint/no-misused-promises": [ + "error", + { + "checksSpreads": false + } + ] +} +``` Examples of code for this rule with `checksSpreads: true`: diff --git a/packages/eslint-plugin/docs/rules/no-namespace.md b/packages/eslint-plugin/docs/rules/no-namespace.md index 5ef63e7b127f..e5f2d431d572 100644 --- a/packages/eslint-plugin/docs/rules/no-namespace.md +++ b/packages/eslint-plugin/docs/rules/no-namespace.md @@ -1,20 +1,19 @@ --- -description: 'Disallow custom TypeScript modules and namespaces.' +description: 'Disallow TypeScript namespaces.' --- > 🛑 This file is source code, not the primary documentation location! 🛑 > > See **https://typescript-eslint.io/rules/no-namespace** for documentation. -Custom TypeScript modules (`module foo {}`) and namespaces (`namespace foo {}`) are considered outdated -ways to organize TypeScript code. ES2015 module syntax is now preferred (`import`/`export`). +TypeScript historically allowed a form of code organization called "custom modules" (`module Example {}`), later renamed to "namespaces" (`namespace Example`). +Namespaces are an outdated way to organize TypeScript code. +ES2015 module syntax is now preferred (`import`/`export`). -This rule still allows the use of TypeScript module declarations to describe external APIs (`declare module 'foo' {}`). +> This rule does not report on the use of TypeScript module declarations to describe external APIs (`declare module 'foo' {}`). ## Examples -This rule aims to standardize the way modules are declared. - Examples of code with the default options: diff --git a/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md b/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md index 77c05fa084db..09bf9be3be84 100644 --- a/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md +++ b/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md @@ -6,18 +6,16 @@ description: 'Disallow non-null assertions in the left operand of a nullish coal > > See **https://typescript-eslint.io/rules/no-non-null-asserted-nullish-coalescing** for documentation. -## Examples +The `??` nullish coalescing runtime operator allows providing a default value when dealing with `null` or `undefined`. +Using a `!` non-null assertion type operator in the left operand of a nullish coalescing operator is redundant, and likely a sign of programmer error or confusion over the two operators. -The nullish coalescing operator is designed to provide a default value when dealing with `null` or `undefined`. -Using non-null assertions in the left operand of the nullish coalescing operator is redundant. +## Examples ### ❌ Incorrect ```ts -/* eslint @typescript-eslint/no-non-null-asserted-nullish-coalescing: "error" */ - foo! ?? bar; foo.bazz! ?? bar; foo!.bazz! ?? bar; @@ -34,8 +32,6 @@ x! ?? ''; ### ✅ Correct ```ts -/* eslint @typescript-eslint/no-non-null-asserted-nullish-coalescing: "error" */ - foo ?? bar; foo ?? bar!; foo!.bazz ?? bar; @@ -47,10 +43,6 @@ let x: string; x! ?? ''; ``` -## When Not To Use It - -If you are not using TypeScript 3.7 (or greater), then you will not need to use this rule, as the nullish coalescing operator is not supported. - ## Further Reading - [TypeScript 3.7 Release Notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) diff --git a/packages/eslint-plugin/docs/rules/no-non-null-asserted-optional-chain.md b/packages/eslint-plugin/docs/rules/no-non-null-asserted-optional-chain.md index 5b4a15c21055..4a6c1607a947 100644 --- a/packages/eslint-plugin/docs/rules/no-non-null-asserted-optional-chain.md +++ b/packages/eslint-plugin/docs/rules/no-non-null-asserted-optional-chain.md @@ -6,50 +6,29 @@ description: 'Disallow non-null assertions after an optional chain expression.' > > See **https://typescript-eslint.io/rules/no-non-null-asserted-optional-chain** for documentation. -## Examples +`?.` optional chain expressions provide `undefined` if an object is `null` or `undefined`. +Using a `!` non-null assertion to assert the result of an `?.` optional chain expression is non-nullable is likely wrong. + +> Most of the time, either the object was not nullable and did not need the `?.` for its property lookup, or the `!` is incorrect and introducing a type safety hole. -Optional chain expressions are designed to return `undefined` if the optional property is nullish. -Using non-null assertions after an optional chain expression is wrong, and introduces a serious type safety hole into your code. +## Examples ### ❌ Incorrect ```ts -/* eslint @typescript-eslint/no-non-null-asserted-optional-chain: "error" */ - foo?.bar!; foo?.bar()!; - -// Prior to TS3.9, foo?.bar!.baz meant (foo?.bar).baz - i.e. the non-null assertion is applied to the entire chain so far. -// For TS3.9 and greater, the non-null assertion is only applied to the property itself, so it's safe. -// The following is incorrect code if you're using less than TS3.9 -foo?.bar!.baz; -foo?.bar!(); -foo?.bar!().baz; ``` ### ✅ Correct ```ts -/* eslint @typescript-eslint/no-non-null-asserted-optional-chain: "error" */ - foo?.bar; -(foo?.bar).baz; -foo?.bar(); foo?.bar(); -foo?.bar().baz; - -// The following is correct code if you're using TS3.9 or greater -foo?.bar!.baz; -foo?.bar!(); -foo?.bar!().baz; ``` -## When Not To Use It - -If you are not using TypeScript 3.7 (or greater), then you will not need to use this rule, as the operator is not supported. - ## Further Reading - [TypeScript 3.7 Release Notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) diff --git a/packages/eslint-plugin/docs/rules/no-non-null-assertion.md b/packages/eslint-plugin/docs/rules/no-non-null-assertion.md index 874e1ea3739b..7e468da58985 100644 --- a/packages/eslint-plugin/docs/rules/no-non-null-assertion.md +++ b/packages/eslint-plugin/docs/rules/no-non-null-assertion.md @@ -6,34 +6,39 @@ description: 'Disallow non-null assertions using the `!` postfix operator.' > > See **https://typescript-eslint.io/rules/no-non-null-assertion** for documentation. +TypeScript's `!` non-null assertion operator asserts to the type system that an expression is non-nullable, as in not `null` or `undefined`. +Using assertions to tell the type system new information is often a sign that code is not fully type-safe. +It's generally better to structure program logic so that TypeScript understands when values may be nullable. + ## Examples -Using non-null assertions cancels the benefits of the strict null-checking mode. + ### ❌ Incorrect ```ts -interface Foo { - bar?: string; +interface Example { + property?: string; } -const foo: Foo = getFoo(); -const includesBaz: boolean = foo.bar!.includes('baz'); +declare const example: Example; +const includesBaz = foo.property!.includes('baz'); ``` ### ✅ Correct ```ts -interface Foo { - bar?: string; +interface Example { + property?: string; } -const foo: Foo = getFoo(); -const includesBaz: boolean = foo.bar?.includes('baz') ?? false; +declare const example: Example; +const includesBaz = foo.property?.includes('baz') ?? false; ``` ## When Not To Use It -If you don't care about strict null-checking, then you will not need this rule. +If your project does not use the `strictNullChecks` compiler option, this rule is likely useless to you. +If your code is often wildly incorrect with respect to strict null-checking, your code may not yet be ready for this rule. diff --git a/packages/eslint-plugin/docs/rules/no-redundant-type-constituents.md b/packages/eslint-plugin/docs/rules/no-redundant-type-constituents.md index d8c3a677a944..69cd6c83af03 100644 --- a/packages/eslint-plugin/docs/rules/no-redundant-type-constituents.md +++ b/packages/eslint-plugin/docs/rules/no-redundant-type-constituents.md @@ -6,8 +6,6 @@ description: 'Disallow members of unions and intersections that do nothing or ov > > See **https://typescript-eslint.io/rules/no-redundant-type-constituents** for documentation. -## Examples - Some types can override some other types ("constituents") in a union or intersection and/or be overridden by some other types. TypeScript's set theory of types includes cases where a constituent type might be useless in the parent union or intersection. @@ -24,6 +22,8 @@ Within `&` intersections: - literal types "override" any primitive types in an intersection - literal types such as `""` "override" any of their primitive types such as `string` +## Examples + ### ❌ Incorrect @@ -64,14 +64,11 @@ type IntersectionNever = string; type IntersectionBooleanLiteral = false; type IntersectionNumberLiteral = 1; type IntersectionStringLiteral = 'foo'; - -type ReturnUnionNever = () => string | never; ``` ## Limitations This rule plays it safe and only works with bottom types, top types, and comparing literal types to primitive types. -It also does not provide an auto-fixer just yet. ## Further Reading diff --git a/packages/eslint-plugin/docs/rules/no-require-imports.md b/packages/eslint-plugin/docs/rules/no-require-imports.md index e8913526fcad..6e75a3d41cd3 100644 --- a/packages/eslint-plugin/docs/rules/no-require-imports.md +++ b/packages/eslint-plugin/docs/rules/no-require-imports.md @@ -15,24 +15,23 @@ Prefer the newer ES6-style imports over `require()`. ### ❌ Incorrect ```ts -var lib = require('lib'); -let lib2 = require('lib2'); -var lib5 = require('lib5'), - lib6 = require('lib6'); -import lib8 = require('lib8'); +const lib1 = require('lib1'); +const { lib2 } = require('lib2'); +import lib3 = require('lib3'); ``` ### ✅ Correct ```ts -import { l } from 'lib'; -var lib3 = load('not_an_import'); -var lib4 = lib2.subImport; -var lib7 = 700; -import lib9 = lib2.anotherSubImport; -import lib10 from 'lib10'; +import * as lib1 from 'lib1'; +import { lib2 } from 'lib2'; +import * as lib3 from 'lib3'; ``` ## When Not To Use It -If you don't care about TypeScript module syntax, then you will not need this rule. +If you don't care about using newer module syntax, then you will not need this rule. + +## Related To + +- [`no-var-requires`](./no-var-requires.md) diff --git a/packages/eslint-plugin/docs/rules/no-this-alias.md b/packages/eslint-plugin/docs/rules/no-this-alias.md index ea8006117989..640d5a6a2b54 100644 --- a/packages/eslint-plugin/docs/rules/no-this-alias.md +++ b/packages/eslint-plugin/docs/rules/no-this-alias.md @@ -6,24 +6,24 @@ description: 'Disallow aliasing `this`.' > > See **https://typescript-eslint.io/rules/no-this-alias** for documentation. -This rule prohibits assigning variables to `this`. +Assigning a variable to `this` instead of properly using arrow lambdas may be a symptom of pre-ES6 practices +or not managing scope well. ## Examples -Assigning a variable to `this` instead of properly using arrow lambdas may be a symptom of pre-ES6 practices -or not managing scope well. + -Instead of storing a reference to `this` and using it inside a `function () {`: +### ❌ Incorrect ```js const self = this; -> + setTimeout(function () { - self.doWork(); + self.doWork(); }); ``` -Use `() =>` arrow lambdas, as they preserve `this` scope for you: +### ✅ Correct ```js setTimeout(() => { @@ -31,13 +31,7 @@ setTimeout(() => { }); ``` -Examples of **incorrect** code for this rule: - -(see the rationale above) - -Examples of **correct** code for this rule: - -(see the rationale above) +## Options ## When Not To Use It diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md b/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md index 693b45e8267a..69c9a33441bd 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md @@ -6,23 +6,20 @@ description: 'Disallow unnecessary equality comparisons against boolean literals > > See **https://typescript-eslint.io/rules/no-unnecessary-boolean-literal-compare** for documentation. -Comparing boolean values to boolean literals is unnecessary, those comparisons result in the same booleans. Using the boolean values directly, or via a unary negation (`!value`), is more concise and clearer. - -## Examples +Comparing boolean values to boolean literals is unnecessary: those comparisons result in the same booleans. +Using the boolean values directly, or via a unary negation (`!value`), is more concise and clearer. This rule ensures that you do not include unnecessary comparisons with boolean literals. A comparison is considered unnecessary if it checks a boolean literal against any variable with just the `boolean` type. -A comparison is **_not_** considered unnecessary if the type is a union of booleans (`string | boolean`, `someObject | boolean`). +A comparison is **_not_** considered unnecessary if the type is a union of booleans (`string | boolean`, `SomeObject | boolean`, etc.). -**Warning**: Do not use this rule when `strictNullChecks` is disabled. -ESLint is not able to distinguish between `false` and `undefined` or `null` values. -This can cause unintended code changes when using autofix. +## Examples -**Note**: Throughout this page, only strict equality (`===` and `!==`) are -used in the examples. However, the implementation of the rule does not -distinguish between strict and loose equality. Any example below that uses -`===` would be treated the same way if `==` was used, and any example below -that uses `!==` would be treated the same way if `!=` was used. +:::note +Throughout this page, only strict equality (`===` and `!==`) are used in the examples. +However, the implementation of the rule does not distinguish between strict and loose equality. +Any example below that uses `===` would be treated the same way if `==` was used, and `!==` would be treated the same way if `!=` was used. +::: @@ -128,3 +125,9 @@ if (!(someNullCondition ?? true)) { | `nullableBooleanVar !== true` | `!nullableBooleanVar` | Only checked/fixed if the `allowComparingNullableBooleansToTrue` option is `false` | | `nullableBooleanVar === false` | `nullableBooleanVar ?? true` | Only checked/fixed if the `allowComparingNullableBooleansToFalse` option is `false` | | `nullableBooleanVar !== false` | `!(nullableBooleanVar ?? true)` | Only checked/fixed if the `allowComparingNullableBooleansToFalse` option is `false` | + +## Not To Use It + +Do not use this rule when `strictNullChecks` is disabled. +ESLint is not able to distinguish between `false` and `undefined` or `null` values. +This can cause unintended code changes when using autofix. diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-condition.md b/packages/eslint-plugin/docs/rules/no-unnecessary-condition.md index 1a55124991bc..8e052f2379fc 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-condition.md +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-condition.md @@ -6,7 +6,8 @@ description: 'Disallow conditionals where the type is always truthy or always fa > > See **https://typescript-eslint.io/rules/no-unnecessary-condition** for documentation. -Any expression being used as a condition must be able to evaluate as truthy or falsy in order to be considered "necessary". Conversely, any expression that always evaluates to truthy or always evaluates to falsy, as determined by the type of the expression, is considered unnecessary and will be flagged by this rule. +Any expression being used as a condition must be able to evaluate as truthy or falsy in order to be considered "necessary". +Conversely, any expression that always evaluates to truthy or always evaluates to falsy, as determined by the type of the expression, is considered unnecessary and will be flagged by this rule. The following expressions are checked: diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-qualifier.md b/packages/eslint-plugin/docs/rules/no-unnecessary-qualifier.md index 22a410158852..6ca2afe17f52 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-qualifier.md +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-qualifier.md @@ -6,29 +6,16 @@ description: 'Disallow unnecessary namespace qualifiers.' > > See **https://typescript-eslint.io/rules/no-unnecessary-qualifier** for documentation. -## Examples +Members of TypeScript enums and namespaces are generally retrieved as qualified property lookups: e.g. `Enum.member`. +However, when accessed within their parent enum or namespace, the qualifier is unnecessary: e.g. just `member` instead of `Enum.member`. +This rule reports when an enum or namespace qualifier is unnecessary. -This rule aims to let users know when a namespace or enum qualifier is unnecessary, -whether used for a type or for a value. +## Examples ### ❌ Incorrect -```ts -namespace A { - export type B = number; - const x: A.B = 3; -} -``` - -```ts -namespace A { - export const x = 3; - export const y = A.x; -} -``` - ```ts enum A { B, @@ -38,46 +25,27 @@ enum A { ```ts namespace A { - export namespace B { - export type T = number; - const x: A.B.T = 3; - } + export type B = number; + const x: A.B = 3; } ``` ### ✅ Correct -```ts -namespace X { - export type T = number; -} - -namespace Y { - export const x: X.T = 3; -} -``` - ```ts enum A { - X, - Y, -} - -enum B { - Z = A.X, + B, + C = B, } ``` ```ts -namespace X { - export type T = number; - namespace Y { - type T = string; - const x: X.T = 0; - } +namespace A { + export type B = number; + const x: B = 3; } ``` ## When Not To Use It -If you don't care about having unneeded namespace or enum qualifiers, then you don't need to use this rule. +If you don't care about having unneeded enum or namespace qualifiers, then you don't need to use this rule. diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-type-arguments.md b/packages/eslint-plugin/docs/rules/no-unnecessary-type-arguments.md index 2f24af3cd95b..43526aec5719 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-type-arguments.md +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-type-arguments.md @@ -6,18 +6,17 @@ description: 'Disallow type arguments that are equal to the default.' > > See **https://typescript-eslint.io/rules/no-unnecessary-type-arguments** for documentation. -Warns if an explicitly specified type argument is the default for that type parameter. - -## Examples - Type parameters in TypeScript may specify a default value. For example: ```ts -function f() {} +function f(...) {...} ``` -It is redundant to provide an explicit type parameter equal to that default. +It is redundant to provide an explicit type parameter equal to that default: e.g. calling `f(...)`. +This rule reports when an explicitly specified type argument is the default for that type parameter. + +## Examples @@ -26,15 +25,21 @@ It is redundant to provide an explicit type parameter equal to that default. ```ts function f() {} f(); +``` +```ts function g() {} g(); +``` +```ts class C {} -function h(c: C) {} new C(); + class D extends C {} +``` +```ts interface I {} class Impl implements I {} ``` @@ -43,15 +48,26 @@ class Impl implements I {} ```ts function f() {} +f(); f(); +``` +```ts function g() {} +g(); g(); +``` +```ts class C {} +new C(); new C(); + +class D extends C {} class D extends C {} +``` +```ts interface I {} class Impl implements I {} ``` diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.md b/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.md index c33ce0010c17..72698d8980a8 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.md +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.md @@ -6,12 +6,12 @@ description: 'Disallow type assertions that do not change the type of an express > > See **https://typescript-eslint.io/rules/no-unnecessary-type-assertion** for documentation. -This rule prohibits using a type assertion that does not change the type of an expression. +TypeScript can be told an expression is a different type than expected using `as` type assertions. +Leaving `as` assertions in the codebase increases visual clutter and harms code readability, so it's generally best practice to remove them if they don't change the type of an expression. +This rule reports when a type assertion does not change the type of an expression. ## Examples -This rule aims to prevent unnecessary type assertions. - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-type-constraint.md b/packages/eslint-plugin/docs/rules/no-unnecessary-type-constraint.md index 07ec4b536d22..b8672d945d50 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-type-constraint.md +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-type-constraint.md @@ -6,15 +6,11 @@ description: 'Disallow unnecessary constraints on generic types.' > > See **https://typescript-eslint.io/rules/no-unnecessary-type-constraint** for documentation. -## Examples - -Type parameters (``) may be "constrained" with an `extends` keyword ([docs](https://www.typescriptlang.org/docs/handbook/generics.html#generic-constraints)). -When not provided, type parameters happen to default to: - -- As of TypeScript 3.9: `unknown` ([docs](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#type-parameters-that-extend-any-no-longer-act-as-any)) -- Before that, as of 3.5: `any` ([docs](https://devblogs.microsoft.com/typescript/announcing-typescript-3-5/#breaking-changes)) +Generic type parameters (``) in TypeScript may be "constrained" with an [`extends` keyword](https://www.typescriptlang.org/docs/handbook/generics.html#generic-constraints). +When no `extends` is provided, type parameters default a constraint to `any`. +It is therefore redundant to `extend` from `any`. -It is therefore redundant to `extend` from these types in later versions of TypeScript. +## Examples @@ -22,24 +18,16 @@ It is therefore redundant to `extend` from these types in later versions of Type ```ts interface FooAny {} -interface FooUnknown {} type BarAny = {}; -type BarUnknown = {}; class BazAny { - quxUnknown() {} -} - -class BazUnknown { - quxUnknown() {} + quxAny() {} } const QuuxAny = () => {}; -const QuuxUnknown = () => {}; function QuuzAny() {} -function QuuzUnknown() {} ``` ### ✅ Correct @@ -50,7 +38,7 @@ interface Foo {} type Bar = {}; class Baz { - qux { } + qux { } } const Quux = () => {}; diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-argument.md b/packages/eslint-plugin/docs/rules/no-unsafe-argument.md index e2f0807ffdd1..6390409827a0 100644 --- a/packages/eslint-plugin/docs/rules/no-unsafe-argument.md +++ b/packages/eslint-plugin/docs/rules/no-unsafe-argument.md @@ -6,14 +6,19 @@ description: 'Disallow calling a function with a value with type `any`.' > > See **https://typescript-eslint.io/rules/no-unsafe-argument** for documentation. +The `any` type in TypeScript is a dangerous "escape hatch" from the type system. +Using `any` disables many type checking rules and is generally best used only as a last resort or when prototyping code. + Despite your best intentions, the `any` type can sometimes leak into your codebase. -Call a function with `any` typed argument are not checked at all by TypeScript, so it creates a potential safety hole, and source of bugs in your codebase. +Calling a function with an `any` typed argument creates a potential safety hole and source of bugs. -## Examples +This rule disallows calling a function with `any` in its arguments. +That includes spreading arrays or tuples with `any` typed elements as function arguments. -This rule disallows calling a function with `any` in its arguments, and it will disallow spreading `any[]`. -This rule also disallows spreading a tuple type with one of its elements typed as `any`. -This rule also compares the argument's type to the variable's type to ensure you don't pass an unsafe `any` in a generic position to a receiver that's expecting a specific type. For example, it will error if you assign `Set` to an argument declared as `Set`. +This rule also compares generic type argument types to ensure you don't pass an unsafe `any` in a generic position to a receiver that's expecting a specific type. +For example, it will error if you pass `Set` as an argument to a parameter declared as `Set`. + +## Examples @@ -66,7 +71,7 @@ foo(new Set(), new Map()); There are cases where the rule allows passing an argument of `any` to `unknown`. -Example of `any` to `unknown` assignment that are allowed. +Example of `any` to `unknown` assignment that are allowed: ```ts declare function foo(arg1: unknown, arg2: Set, arg3: unknown[]): void; diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-assignment.md b/packages/eslint-plugin/docs/rules/no-unsafe-assignment.md index 1d1d4808824e..98228f81683b 100644 --- a/packages/eslint-plugin/docs/rules/no-unsafe-assignment.md +++ b/packages/eslint-plugin/docs/rules/no-unsafe-assignment.md @@ -6,13 +6,18 @@ description: 'Disallow assigning a value with type `any` to variables and proper > > See **https://typescript-eslint.io/rules/no-unsafe-assignment** for documentation. -Despite your best intentions, the `any` type can sometimes leak into your codebase. -Assigning an `any` typed value to a variable can be hard to pick up on, particularly if it leaks in from an external library. Operations on the variable will not be checked at all by TypeScript, so it creates a potential safety hole, and source of bugs in your codebase. +The `any` type in TypeScript is a dangerous "escape hatch" from the type system. +Using `any` disables many type checking rules and is generally best used only as a last resort or when prototyping code. -## Examples +Despite your best intentions, the `any` type can sometimes leak into your codebase. +Assigning an `any` typed value to a variable can be hard to pick up on, particularly if it leaks in from an external library. This rule disallows assigning `any` to a variable, and assigning `any[]` to an array destructuring. -This rule also compares the assigned type to the variable's type to ensure you don't assign an unsafe `any` in a generic position to a receiver that's expecting a specific type. For example, it will error if you assign `Set` to a variable declared as `Set`. + +This rule also compares generic type argument types to ensure you don't pass an unsafe `any` in a generic position to a receiver that's expecting a specific type. +For example, it will error if you assign `Set` to a variable declared as `Set`. + +## Examples @@ -68,7 +73,7 @@ const x: Set>> = new Set>>(); There are cases where the rule allows assignment of `any` to `unknown`. -Example of `any` to `unknown` assignment that are allowed. +Example of `any` to `unknown` assignment that are allowed: ```ts const x: unknown = y as any; diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-call.md b/packages/eslint-plugin/docs/rules/no-unsafe-call.md index a04a734d8775..8fddb2774b61 100644 --- a/packages/eslint-plugin/docs/rules/no-unsafe-call.md +++ b/packages/eslint-plugin/docs/rules/no-unsafe-call.md @@ -6,12 +6,15 @@ description: 'Disallow calling a value with type `any`.' > > See **https://typescript-eslint.io/rules/no-unsafe-call** for documentation. +The `any` type in TypeScript is a dangerous "escape hatch" from the type system. +Using `any` disables many type checking rules and is generally best used only as a last resort or when prototyping code. + Despite your best intentions, the `any` type can sometimes leak into your codebase. -The arguments to, and return value of calling an `any` typed variable are not checked at all by TypeScript, so it creates a potential safety hole, and source of bugs in your codebase. +Calling an `any`-typed value as a function creates a potential type safety hole and source of bugs in your codebase. -## Examples +This rule disallows calling any value that is typed as `any`. -This rule disallows calling any variable that is typed as `any`. +## Examples diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-member-access.md b/packages/eslint-plugin/docs/rules/no-unsafe-member-access.md index 5aa7a6af67d7..dfefaccd8b44 100644 --- a/packages/eslint-plugin/docs/rules/no-unsafe-member-access.md +++ b/packages/eslint-plugin/docs/rules/no-unsafe-member-access.md @@ -6,13 +6,16 @@ description: 'Disallow member access on a value with type `any`.' > > See **https://typescript-eslint.io/rules/no-unsafe-member-access** for documentation. -Despite your best intentions, the `any` type can sometimes leak into your codebase. -Member access on `any` typed variables is not checked at all by TypeScript, so it creates a potential safety hole, and source of bugs in your codebase. +The `any` type in TypeScript is a dangerous "escape hatch" from the type system. +Using `any` disables many type checking rules and is generally best used only as a last resort or when prototyping code. -## Examples +Despite your best intentions, the `any` type can sometimes leak into your codebase. +Accessing a member of an `any`-typed value creates a potential type safety hole and source of bugs in your codebase. This rule disallows member access on any variable that is typed as `any`. +## Examples + ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-unsafe-return.md b/packages/eslint-plugin/docs/rules/no-unsafe-return.md index 17c1a6f6bc2a..796580f23dd1 100644 --- a/packages/eslint-plugin/docs/rules/no-unsafe-return.md +++ b/packages/eslint-plugin/docs/rules/no-unsafe-return.md @@ -6,13 +6,18 @@ description: 'Disallow returning a value with type `any` from a function.' > > See **https://typescript-eslint.io/rules/no-unsafe-return** for documentation. -Despite your best intentions, the `any` type can sometimes leak into your codebase. -Returned `any` typed values are not checked at all by TypeScript, so it creates a potential safety hole, and source of bugs in your codebase. +The `any` type in TypeScript is a dangerous "escape hatch" from the type system. +Using `any` disables many type checking rules and is generally best used only as a last resort or when prototyping code. -## Examples +Despite your best intentions, the `any` type can sometimes leak into your codebase. +Returning an an `any`-typed value from a function creates a potential type safety hole and source of bugs in your codebase. This rule disallows returning `any` or `any[]` from a function. -This rule also compares the return type to the function's declared/inferred return type to ensure you don't return an unsafe `any` in a generic position to a receiver that's expecting a specific type. For example, it will error if you return `Set` from a function declared as returning `Set`. + +This rule also compares generic type argument types to ensure you don't return an unsafe `any` in a generic position to a function that's expecting a specific type. +For example, it will error if you return `Set` from a function declared as returning `Set`. + +## Examples @@ -81,7 +86,7 @@ const assignability2: TAssign = () => new Set(['foo']); There are cases where the rule allows to return `any` to `unknown`. -Examples of `any` to `unknown` return that are allowed. +Examples of `any` to `unknown` return that are allowed: ```ts function foo1(): unknown { diff --git a/packages/eslint-plugin/docs/rules/no-useless-empty-export.md b/packages/eslint-plugin/docs/rules/no-useless-empty-export.md index aaf2b08792a2..9358e954b3ff 100644 --- a/packages/eslint-plugin/docs/rules/no-useless-empty-export.md +++ b/packages/eslint-plugin/docs/rules/no-useless-empty-export.md @@ -6,16 +6,18 @@ description: "Disallow empty exports that don't change anything in a module file > > See **https://typescript-eslint.io/rules/no-useless-empty-export** for documentation. -## Examples - An empty `export {}` statement is sometimes useful in TypeScript code to turn a file that would otherwise be a script file into a module file. -Per the TypeScript Handbook [Modules](https://www.typescriptlang.org/docs/handbook/modules.html) page: +Per the [TypeScript Handbook Modules page](https://www.typescriptlang.org/docs/handbook/modules.html): > In TypeScript, just as in ECMAScript 2015, any file containing a top-level import or export is considered a module. > Conversely, a file without any top-level import or export declarations is treated as a script whose contents are available in the global scope (and therefore to modules as well). However, an `export {}` statement does nothing if there are any other top-level import or export statements in a file. +This rule reports an `export {}` that doesn't do anything in a file already using ES modules. + +## Examples + ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/no-var-requires.md b/packages/eslint-plugin/docs/rules/no-var-requires.md index 352da6f5a9f7..7230e4e8aebc 100644 --- a/packages/eslint-plugin/docs/rules/no-var-requires.md +++ b/packages/eslint-plugin/docs/rules/no-var-requires.md @@ -30,4 +30,8 @@ import foo from 'foo'; ## When Not To Use It -If you don't care about TypeScript module syntax, then you will not need this rule. +If you don't care about using newer module syntax, then you will not need this rule. + +## Related To + +- [`no-require-imports`](./no-require-imports.md) diff --git a/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.md b/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.md index 662a99880be8..8f068f062e66 100644 --- a/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.md +++ b/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.md @@ -6,7 +6,13 @@ description: 'Enforce non-null assertions over explicit type casts.' > > See **https://typescript-eslint.io/rules/non-nullable-type-assertion-style** for documentation. -This rule detects when an `as` cast is doing the same job as a `!` would, and suggests fixing the code to be an `!`. +There are two common ways to assert to TypeScript that a value is its type without `null` or `undefined`: + +- `!`: Non-null assertion +- `as`: Traditional type assertion with a coincidentally equivalent type + +`!` non-null assertions are generally preferred for requiring less code and being harder to fall out of sync as types change. +This rule reports when an `as` cast is doing the same job as a `!` would, and suggests fixing the code to be an `!`. ## Examples diff --git a/packages/eslint-plugin/docs/rules/parameter-properties.md b/packages/eslint-plugin/docs/rules/parameter-properties.md index 383a432b08ac..e0e30ddbd3ae 100644 --- a/packages/eslint-plugin/docs/rules/parameter-properties.md +++ b/packages/eslint-plugin/docs/rules/parameter-properties.md @@ -6,13 +6,10 @@ description: 'Require or disallow parameter properties in class constructors.' > > See **https://typescript-eslint.io/rules/parameter-properties** for documentation. -Parameter properties can be confusing to those new to TypeScript as they are less explicit than other ways -of declaring and initializing class members. +TypeScript includes a "parameter properties" shorthand for declaring a class constructor parameter and class property in one location. +Parameter properties can be confusing to those new to TypeScript as they are less explicit than other ways of declaring and initializing class members. -## Examples - -This rule disallows the use of parameter properties in constructors, forcing the user to explicitly -declare all properties in the class. +This rule can be configured to always disallow the use of parameter properties or enforce their usage when possible. ## Options diff --git a/packages/eslint-plugin/docs/rules/prefer-as-const.md b/packages/eslint-plugin/docs/rules/prefer-as-const.md index 9f2ce9ba2744..628c573044cb 100644 --- a/packages/eslint-plugin/docs/rules/prefer-as-const.md +++ b/packages/eslint-plugin/docs/rules/prefer-as-const.md @@ -6,7 +6,13 @@ description: 'Enforce the use of `as const` over literal type.' > > See **https://typescript-eslint.io/rules/prefer-as-const** for documentation. -This rule recommends usage of `const` assertion when type primitive value is equal to type. +There are two common ways to tell TypeScript that a literal value should be interpreted as its literal type (e.g. `2`) rather than general primitive type (e.g. `number`); + +- `as const`: telling TypeScript to infer the literal type automatically +- `as` with the literal type: explicitly telling the literal type to TypeScript + +`as const` is generally preferred, as it doesn't require re-typing the literal value. +This rule reports when an `as` with an explicit literal type can be replaced with an `as const`. ## Examples diff --git a/packages/eslint-plugin/docs/rules/prefer-enum-initializers.md b/packages/eslint-plugin/docs/rules/prefer-enum-initializers.md index 7950e704dce5..1c4204b665c0 100644 --- a/packages/eslint-plugin/docs/rules/prefer-enum-initializers.md +++ b/packages/eslint-plugin/docs/rules/prefer-enum-initializers.md @@ -6,30 +6,14 @@ description: 'Require each enum member value to be explicitly initialized.' > > See **https://typescript-eslint.io/rules/prefer-enum-initializers** for documentation. -This rule recommends having each `enum`s member value explicitly initialized. +TypeScript `enum`s are a practical way to organize semantically related constant values. +Members of `enum`s that don't have explicit values are by default given sequentially increasing numbers. -`enum`s are a practical way to organize semantically related constant values. However, by implicitly defining values, `enum`s can lead to unexpected bugs if it's modified without paying attention to the order of its items. +In projects where the value of `enum` members are important, allowing implicit values for enums can cause bugs if `enum`s are modified over time. -## Examples - -`enum`s infers sequential numbers automatically when initializers are omitted: - -```ts -enum Status { - Open, // infer 0 - Closed, // infer 1 -} -``` +This rule recommends having each `enum` member value explicitly initialized. -If a new member is added to the top of `Status`, both `Open` and `Closed` would have its values altered: - -```ts -enum Status { - Pending, // infer 0 - Open, // infer 1 - Closed, // infer 2 -} -``` +## Examples diff --git a/packages/eslint-plugin/docs/rules/prefer-for-of.md b/packages/eslint-plugin/docs/rules/prefer-for-of.md index 13c36bc191f9..83b7846acb0a 100644 --- a/packages/eslint-plugin/docs/rules/prefer-for-of.md +++ b/packages/eslint-plugin/docs/rules/prefer-for-of.md @@ -6,37 +6,38 @@ description: 'Enforce the use of `for-of` loop over the standard `for` loop wher > > See **https://typescript-eslint.io/rules/prefer-for-of** for documentation. +Many developers default to writing `for (let i = 0; i < ...` loops to iterate over arrays. +However, in many of those arrays, the loop iterator variable (e.g. `i`) is only used to access the respective element of the array. +In those cases, a `for-of` loop is easier to read and write. + This rule recommends a for-of loop when the loop index is only used to read from an array that is being iterated. ## Examples -For cases where the index is only used to read from the array being iterated, a for-of loop is easier to read and write. - ### ❌ Incorrect ```js -for (let i = 0; i < arr.length; i++) { - console.log(arr[i]); +declare const array: string[]; + +for (let i = 0; i < array.length; i++) { + console.log(array[i]); } ``` ### ✅ Correct ```js -for (const x of arr) { - console.log(x); -} +declare const array: string[]; -for (let i = 0; i < arr.length; i++) { - // i is used to write to arr, so for-of could not be used. - arr[i] = 0; +for (const x of array) { + console.log(x); } -for (let i = 0; i < arr.length; i++) { - // i is used independent of arr, so for-of could not be used. - console.log(i, arr[i]); +for (let i = 0; i < array.length; i++) { + // i is used, so for-of could not be used. + console.log(i, array[i]); } ``` diff --git a/packages/eslint-plugin/docs/rules/prefer-function-type.md b/packages/eslint-plugin/docs/rules/prefer-function-type.md index 40980f0d7250..5ec8490a4879 100644 --- a/packages/eslint-plugin/docs/rules/prefer-function-type.md +++ b/packages/eslint-plugin/docs/rules/prefer-function-type.md @@ -6,34 +6,35 @@ description: 'Enforce using function types instead of interfaces with call signa > > See **https://typescript-eslint.io/rules/prefer-function-type** for documentation. -## Examples +TypeScript allows for two common ways to declare a type for a function: + +- Function type: `() => string` +- Object type with a signature: `{ (): string }` + +The function type form is generally preferred when possible for being more succinct. This rule suggests using a function type instead of an interface or object type literal with a single call signature. +## Examples + ### ❌ Incorrect ```ts -interface Foo { +interface Example { (): string; } ``` ```ts -function foo(bar: { (): number }): number { - return bar(); +function foo(example: { (): number }): number { + return example(); } ``` ```ts -interface Foo extends Function { - (): void; -} -``` - -```ts -interface MixinMethod { +interface ReturnsSelf { // returns the function itself, not the `this` argument. (arg: string): this; } @@ -42,12 +43,20 @@ interface MixinMethod { ### ✅ Correct ```ts -interface Foo { - (): void; - bar: number; +type Example = () => string; +``` + +```ts +function foo(example: () => number): number { + return bar(); } ``` +```ts +// returns the function itself, not the `this` argument. +type ReturnsSelf = (arg: string) => ReturnsSelf; +``` + ```ts function foo(bar: { (): string; baz: number }): string { return bar(); @@ -63,13 +72,6 @@ interface Bar extends Foo { } ``` -```ts -// returns the `this` argument of function, retaining it's type. -type MixinMethod = (this: TSelf, arg: string) => TSelf; -// a function that returns itself is much clearer in this form. -type ReturnsSelf = (arg: string) => ReturnsSelf; -``` - ```ts // multiple call signatures (overloads) is allowed: interface Overloaded { diff --git a/packages/eslint-plugin/docs/rules/prefer-includes.md b/packages/eslint-plugin/docs/rules/prefer-includes.md index c927cc7f8294..8c1a709c2ded 100644 --- a/packages/eslint-plugin/docs/rules/prefer-includes.md +++ b/packages/eslint-plugin/docs/rules/prefer-includes.md @@ -6,32 +6,28 @@ description: 'Enforce `includes` method over `indexOf` method.' > > See **https://typescript-eslint.io/rules/prefer-includes** for documentation. -Until ES5, we were using `String#indexOf` method to check whether a string contains an arbitrary substring or not. -Until ES2015, we were using `Array#indexOf` method to check whether an array contains an arbitrary value or not. +Prior to ES2015, `Array#indexOf` and `String#indexOf` comparisons against `-1` were the standard ways to check whether a value exists in an array or string, respectively. +Alternatives that are easier to read and write now exist: ES2015 added `String#includes` and ES2016 added `Array#includes`. -ES2015 has added `String#includes` and ES2016 has added `Array#includes`. -It makes code more understandable if we use those `includes` methods for the purpose. - -## Examples - -This rule is aimed at suggesting `includes` method if `indexOf` method was used to check whether an object contains an arbitrary value or not. +This rule reports when an `.indexOf` call can be replaced with an `.includes`. +Additionally, this rule reports the tests of simple regular expressions in favor of `String#includes`. -If the receiver object of the `indexOf` method call has `includes` method and the two methods have the same parameters, this rule does suggestion. -There are such types: `String`, `Array`, `ReadonlyArray`, and typed arrays. +> This rule will report on any receiver object of an `indexOf` method call that has an `includes` method where the two methods have the same parameters. +> Matching types include: `String`, `Array`, `ReadonlyArray`, and typed arrays. -Additionally, this rule reports the tests of simple regular expressions in favor of `String#includes`. +## Examples ### ❌ Incorrect ```ts -let str: string; -let array: any[]; -let readonlyArray: ReadonlyArray; -let typedArray: UInt8Array; -let maybe: string; -let userDefined: { +const str: string; +const array: any[]; +const readonlyArray: ReadonlyArray; +const typedArray: UInt8Array; +const maybe: string; +const userDefined: { indexOf(x: any): number; includes(x: any): boolean; }; @@ -43,32 +39,36 @@ typedArray.indexOf(value) > -1; maybe?.indexOf('') !== -1; userDefined.indexOf(value) >= 0; -// simple RegExp test -/foo/.test(str); +/example/.test(str); ``` ### ✅ Correct ```ts -let array: any[]; -let readonlyArray: ReadonlyArray; -let typedArray: UInt8Array; -let userDefined: { +const str: string; +const array: any[]; +const readonlyArray: ReadonlyArray; +const typedArray: UInt8Array; +const maybe: string; +const userDefined: { indexOf(x: any): number; includes(x: any): boolean; }; -let mismatchExample: { - indexOf(x: any, fromIndex?: number): number; - includes(x: any): boolean; -}; str.includes(value); array.includes(value); readonlyArray.includes(value); typedArray.includes(value); +maybe?.includes(''); userDefined.includes(value); -// the two methods have different parameters. +str.includes('example'); + +// The two methods have different parameters. +declare const mismatchExample: { + indexOf(x: unknown, fromIndex?: number): number; + includes(x: unknown): boolean; +}; mismatchExample.indexOf(value) >= 0; ``` diff --git a/packages/eslint-plugin/docs/rules/prefer-literal-enum-member.md b/packages/eslint-plugin/docs/rules/prefer-literal-enum-member.md index 071bb49b473f..6d9017e761b7 100644 --- a/packages/eslint-plugin/docs/rules/prefer-literal-enum-member.md +++ b/packages/eslint-plugin/docs/rules/prefer-literal-enum-member.md @@ -6,7 +6,9 @@ description: 'Require all enum members to be literal values.' > > See **https://typescript-eslint.io/rules/prefer-literal-enum-member** for documentation. -TypeScript allows the value of an enum member to be many different kinds of valid JavaScript expressions. However, because enums create their own scope whereby each enum member becomes a variable in that scope, unexpected values could be used at runtime. Example: +TypeScript allows the value of an enum member to be many different kinds of valid JavaScript expressions. +However, because enums create their own scope whereby each enum member becomes a variable in that scope, developers are often surprised at the resultant values. +For example: ```ts const imOutside = 2; @@ -21,15 +23,12 @@ enum Foo { } ``` -The answer is that `Foo.c` will be `1` at runtime. The [playground](https://www.typescriptlang.org/play/#src=const%20imOutside%20%3D%202%3B%0D%0Aconst%20b%20%3D%202%3B%0D%0Aenum%20Foo%20%7B%0D%0A%20%20%20%20outer%20%3D%20imOutside%2C%0D%0A%20%20%20%20a%20%3D%201%2C%0D%0A%20%20%20%20b%20%3D%20a%2C%0D%0A%20%20%20%20c%20%3D%20b%2C%0D%0A%20%20%20%20%2F%2F%20does%20c%20%3D%3D%20Foo.b%20%3D%3D%20Foo.c%20%3D%3D%201%3F%0D%0A%20%20%20%20%2F%2F%20or%20does%20c%20%3D%3D%20b%20%3D%3D%202%3F%0D%0A%7D) illustrates this quite nicely. +> The answer is that `Foo.c` will be `1` at runtime [[TypeScript playground](https://www.typescriptlang.org/play/#src=const%20imOutside%20%3D%202%3B%0D%0Aconst%20b%20%3D%202%3B%0D%0Aenum%20Foo%20%7B%0D%0A%20%20%20%20outer%20%3D%20imOutside%2C%0D%0A%20%20%20%20a%20%3D%201%2C%0D%0A%20%20%20%20b%20%3D%20a%2C%0D%0A%20%20%20%20c%20%3D%20b%2C%0D%0A%20%20%20%20%2F%2F%20does%20c%20%3D%3D%20Foo.b%20%3D%3D%20Foo.c%20%3D%3D%201%3F%0D%0A%20%20%20%20%2F%2F%20or%20does%20c%20%3D%3D%20b%20%3D%3D%202%3F%0D%0A%7D)]. -## Examples - -This rule is meant to prevent unexpected results in code by requiring the use of literal values as enum members to prevent unexpected runtime behavior. Template literals, arrays, objects, constructors, and all other expression types can end up using a variable from its scope or the parent scope, which can result in the same unexpected behavior at runtime. +Therefore, it's often better to prevent unexpected results in code by requiring the use of literal values as enum members. +This rule reports when an enum member is given a value that is not a literal. -## Options - -- `allowBitwiseExpressions` set to `true` will allow you to use bitwise expressions in enum initializer (Default: `false`). +## Examples @@ -60,7 +59,9 @@ enum Valid { -### `allowBitwiseExpressions` +## Options + +- `allowBitwiseExpressions` set to `true` will allow you to use bitwise expressions in enum initializer (Default: `false`). Examples of code for the `{ "allowBitwiseExpressions": true }` option: diff --git a/packages/eslint-plugin/docs/rules/prefer-namespace-keyword.md b/packages/eslint-plugin/docs/rules/prefer-namespace-keyword.md index 6457045547f0..f25b124c776a 100644 --- a/packages/eslint-plugin/docs/rules/prefer-namespace-keyword.md +++ b/packages/eslint-plugin/docs/rules/prefer-namespace-keyword.md @@ -6,12 +6,35 @@ description: 'Require using `namespace` keyword over `module` keyword to declare > > See **https://typescript-eslint.io/rules/prefer-namespace-keyword** for documentation. -In an effort to prevent further confusion between custom TypeScript modules and the new ES2015 modules, starting -with TypeScript `v1.5` the keyword `namespace` is now the preferred way to declare custom TypeScript modules. +TypeScript historically allowed a form of code organization called "custom modules" (`module Example {}`), later renamed to "namespaces" (`namespace Example`). + +Namespaces are an outdated way to organize TypeScript code. +ES2015 module syntax is now preferred (`import`/`export`). + +For projects still using custom modules / namespaces, it's preferred to refer to them as namespaces. +This rule reports when the `module` keyword is used instead of `namespace`. + +> This rule does not report on the use of TypeScript module declarations to describe external APIs (`declare module 'foo' {}`). ## Examples -This rule aims to standardize the way modules are declared. + + +### ❌ Incorrect + +```ts +module Example {} +``` + +### ✅ Correct + +```ts +namespace Example {} + +declare module 'foo' {} +``` + + ## When Not To Use It diff --git a/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md b/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md index 6aa0c0d4f86e..5be277ecc733 100644 --- a/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md +++ b/packages/eslint-plugin/docs/rules/prefer-nullish-coalescing.md @@ -6,65 +6,13 @@ description: 'Enforce using the nullish coalescing operator instead of logical c > > See **https://typescript-eslint.io/rules/prefer-nullish-coalescing** for documentation. -TypeScript 3.7 added support for the nullish coalescing operator. -This operator allows you to safely cascade a value when dealing with `null` or `undefined`. +The `??` nullish coalescing runtime operator allows providing a default value when dealing with `null` or `undefined`. +Because the nullish coalescing operator _only_ coalesces when the original value is `null` or `undefined`, it is much safer than relying upon logical OR operator chaining `||`, which coalesces on any _falsy_ value. -```ts -function myFunc(foo: string | null) { - return foo ?? 'a string'; -} - -// is equivalent to - -function myFunc(foo: string | null) { - return foo !== null && foo !== undefined ? foo : 'a string'; -} -``` - -Because the nullish coalescing operator _only_ coalesces when the original value is `null` or `undefined`, it is much safer than relying upon logical OR operator chaining `||`; which coalesces on any _falsy_ value: - -```ts -const emptyString = ''; - -const nullish1 = emptyString ?? 'unsafe'; -const logical1 = emptyString || 'unsafe'; - -// nullish1 === '' -// logical1 === 'unsafe' - -declare const nullString: string | null; - -const nullish2 = nullString ?? 'safe'; -const logical2 = nullString || 'safe'; - -// nullish2 === 'safe' -// logical2 === 'safe' -``` - -## Examples - -This rule aims enforce the usage of the safer operator. +This rule reports when an `||` operator can be safely replaced with a `??`. ## Options -```ts -type Options = [ - { - ignoreTernaryTests?: boolean; - ignoreConditionalTests?: boolean; - ignoreMixedLogicalExpressions?: boolean; - }, -]; - -const defaultOptions = [ - { - ignoreTernaryTests: true; - ignoreConditionalTests: true, - ignoreMixedLogicalExpressions: true, - }, -]; -``` - ### `ignoreTernaryTests` Setting this option to `true` (the default) will cause the rule to ignore any ternary expressions that could be simplified by using the nullish coalescing operator. diff --git a/packages/eslint-plugin/docs/rules/prefer-optional-chain.md b/packages/eslint-plugin/docs/rules/prefer-optional-chain.md index d4b709bbb890..cff46dfdf49b 100644 --- a/packages/eslint-plugin/docs/rules/prefer-optional-chain.md +++ b/packages/eslint-plugin/docs/rules/prefer-optional-chain.md @@ -6,53 +6,13 @@ description: 'Enforce using concise optional chain expressions instead of chaine > > See **https://typescript-eslint.io/rules/prefer-optional-chain** for documentation. -TypeScript 3.7 added support for the optional chain operator. -This operator allows you to safely access properties and methods on objects when they are potentially `null` or `undefined`. - -```ts -type T = { - a?: { - b?: { - c: string; - method?: () => void; - }; - }; -}; - -function myFunc(foo: T | null) { - return foo?.a?.b?.c; -} -// is roughly equivalent to -function myFunc(foo: T | null) { - return foo && foo.a && foo.a.b && foo.a.b.c; -} -// or -function myFunc(foo: T | null) { - return (((foo || {}).a || {}).b || {}).c; -} - -function myFunc(foo: T | null) { - return foo?.['a']?.b?.c; -} -// is roughly equivalent to -function myFunc(foo: T | null) { - return foo && foo['a'] && foo['a'].b && foo['a'].b.c; -} - -function myFunc(foo: T | null) { - return foo?.a?.b?.method?.(); -} -// is roughly equivalent to -function myFunc(foo: T | null) { - return foo && foo.a && foo.a.b && foo.a.b.method && foo.a.b.method(); -} -``` - +`?.` optional chain expressions provide `undefined` if an object is `null` or `undefined`. Because the optional chain operator _only_ chains when the property value is `null` or `undefined`, it is much safer than relying upon logical AND operator chaining `&&`; which chains on any _truthy_ value. +It is also often less code to use `?.` optional chaining than `&&` truthiness checks. -## Examples +This rule reports on code where an `&&` operator can be safely replaced with `?.` optional chaining. -This rule aims enforce the usage of the safer operator. +## Examples @@ -85,11 +45,15 @@ foo?.a?.b?.method?.(); foo?.a?.b?.c?.d?.e; ``` -**Note:** there are a few edge cases where this rule will false positive. Use your best judgement when evaluating reported errors. + + +:::note +There are a few edge cases where this rule will false positive. Use your best judgement when evaluating reported errors. +::: ## When Not To Use It -If you are not using TypeScript 3.7 (or greater), then you will not be able to use this rule, as the operator is not supported. +If you don't mind using more explicit `&&`s, you don't need this rule. ## Further Reading diff --git a/packages/eslint-plugin/docs/rules/prefer-readonly-parameter-types.md b/packages/eslint-plugin/docs/rules/prefer-readonly-parameter-types.md index 644ad742ffa9..b1e912abe379 100644 --- a/packages/eslint-plugin/docs/rules/prefer-readonly-parameter-types.md +++ b/packages/eslint-plugin/docs/rules/prefer-readonly-parameter-types.md @@ -10,8 +10,6 @@ Mutating function arguments can lead to confusing, hard to debug behavior. Whilst it's easy to implicitly remember to not modify function arguments, explicitly typing arguments as readonly provides clear contract to consumers. This contract makes it easier for a consumer to reason about if a function has side-effects. -## Examples - This rule allows you to enforce that function parameters resolve to readonly types. A type is considered readonly if: @@ -21,6 +19,8 @@ A type is considered readonly if: - it is a readonly tuple type whose elements are all considered readonly. - it is an object type whose properties are all marked as readonly, and whose values are all considered readonly. +## Examples + ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/prefer-readonly.md b/packages/eslint-plugin/docs/rules/prefer-readonly.md index 016e3e1db95e..774b55b39ffa 100644 --- a/packages/eslint-plugin/docs/rules/prefer-readonly.md +++ b/packages/eslint-plugin/docs/rules/prefer-readonly.md @@ -6,13 +6,13 @@ description: "Require private members to be marked as `readonly` if they're neve > > See **https://typescript-eslint.io/rules/prefer-readonly** for documentation. -This rule enforces that private members are marked as `readonly` if they're never modified outside of the constructor. - -## Examples - Member variables with the privacy `private` are never permitted to be modified outside of their declaring class. If that class never modifies their value, they may safely be marked as `readonly`. +This rule reports on private members are marked as `readonly` if they're never modified outside of the constructor. + +## Examples + ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/prefer-reduce-type-parameter.md b/packages/eslint-plugin/docs/rules/prefer-reduce-type-parameter.md index e5599cf44ac4..520a25a653b5 100644 --- a/packages/eslint-plugin/docs/rules/prefer-reduce-type-parameter.md +++ b/packages/eslint-plugin/docs/rules/prefer-reduce-type-parameter.md @@ -12,16 +12,16 @@ Since these values are empty, their types are not usable: - `[]` has type `never[]`, which can't have items pushed into it as nothing is type `never` - `{}` has type `{}`, which doesn't have an index signature and so can't have properties added to it -A common solution to this problem is to cast the initial value. While this will work, it's not the most optimal -solution as casting has subtle effects on the underlying types that can allow bugs to slip in. +A common solution to this problem is to use an `as` assertion on the initial value. +While this will work, it's not the most optimal solution as type assertions have subtle effects on the underlying types that can allow bugs to slip in. -A better (and lesser known) solution is to pass the type in as a generic parameter to `Array#reduce` explicitly. +A better solution is to pass the type in as a generic type argument to `Array#reduce` explicitly. This means that TypeScript doesn't have to try to infer the type, and avoids the common pitfalls that come with casting. -## Examples +This rule looks for calls to `Array#reduce`, and reports if an initial value is being passed & asserted. +It will suggest instead pass the asserted type to `Array#reduce` as a generic type argument. -This rule looks for calls to `Array#reduce`, and warns if an initial value is being passed & casted, -suggesting instead to pass the cast type to `Array#reduce` as its generic parameter. +## Examples diff --git a/packages/eslint-plugin/docs/rules/prefer-regexp-exec.md b/packages/eslint-plugin/docs/rules/prefer-regexp-exec.md index aa1cfab63f27..0d9f127be384 100644 --- a/packages/eslint-plugin/docs/rules/prefer-regexp-exec.md +++ b/packages/eslint-plugin/docs/rules/prefer-regexp-exec.md @@ -6,17 +6,14 @@ description: 'Enforce `RegExp#exec` over `String#match` if no global flag is pro > > See **https://typescript-eslint.io/rules/prefer-regexp-exec** for documentation. -As `String#match` is defined to be the same as `RegExp#exec` when the regular expression does not include the `g` flag, prefer a consistent usage. +`String#match` is defined to work the same as `RegExp#exec` when the regular expression does not include the `g` flag. +Keeping to consistently using one of the two can help improve code readability. -## Examples - -This rule is aimed at enforcing a consistent way to apply regular expressions to strings. +This rule reports when a `String#match` call can be replaced with an equivalent `RegExp#exec`. -From [`String#match` on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match): +> `RegExp#exec` may also be slightly faster than `String#match`; this is the reason to choose it as the preferred usage. -> If the regular expression does not include the g flag, returns the same result as `RegExp.exec()`. - -`RegExp#exec` may also be slightly faster than `String#match`; this is the reason to choose it as the preferred usage. +## Examples @@ -46,4 +43,4 @@ search.exec(text); ## When Not To Use It -If you prefer consistent use of `String#match` for both, with `g` flag and without it, you can turn this rule off. +If you prefer consistent use of `String#match` for both with `g` flag and without it, you can turn this rule off. diff --git a/packages/eslint-plugin/docs/rules/prefer-return-this-type.md b/packages/eslint-plugin/docs/rules/prefer-return-this-type.md index cc85dbd95b08..b09c03ba52fc 100644 --- a/packages/eslint-plugin/docs/rules/prefer-return-this-type.md +++ b/packages/eslint-plugin/docs/rules/prefer-return-this-type.md @@ -6,12 +6,17 @@ description: 'Enforce that `this` is used when only `this` type is returned.' > > See **https://typescript-eslint.io/rules/prefer-return-this-type** for documentation. -[Method chaining](https://en.wikipedia.org/wiki/Method_chaining) is a common pattern in OOP languages and TypeScript provides a special [polymorphic this type](https://www.typescriptlang.org/docs/handbook/2/classes.html#this-types). -If any type other than `this` is specified as the return type of these chaining methods, TypeScript will fail to cast it when invoking in subclass. +[Method chaining](https://en.wikipedia.org/wiki/Method_chaining) is a common pattern in OOP languages and TypeScript provides a special [polymorphic `this` type](https://www.typescriptlang.org/docs/handbook/2/classes.html#this-types) to facilitate it. +Class methods that explicitly declare a return type of the class name instead of `this` make it harder for extending classes to call that method: the returned object will be typed as the base class, not the derived class. + +This rule reports when a class method declares a return type of that class name instead of `this`. ```ts class Animal { eat(): Animal { + // ~~~~~~ + // Either removing this type annotation or replacing + // it with `this` would remove the type error below. console.log("I'm moving!"); return this; } @@ -25,28 +30,10 @@ class Cat extends Animal { } const cat = new Cat(); +cat.eat().meow(); +// ~~~~ // Error: Property 'meow' does not exist on type 'Animal'. // because `eat` returns `Animal` and not all animals meow. -cat.eat().meow(); - -// the error can be fixed by removing the return type of `eat` or use `this` as the return type. -class Animal { - eat(): this { - console.log("I'm moving!"); - return this; - } -} - -class Cat extends Animal { - meow(): this { - console.log('Meow~'); - return this; - } -} - -const cat = new Cat(); -// no errors. Because `eat` returns `Cat` now -cat.eat().meow(); ``` ## Examples diff --git a/packages/eslint-plugin/docs/rules/prefer-string-starts-ends-with.md b/packages/eslint-plugin/docs/rules/prefer-string-starts-ends-with.md index e1cd91c584d6..573ce53ed09d 100644 --- a/packages/eslint-plugin/docs/rules/prefer-string-starts-ends-with.md +++ b/packages/eslint-plugin/docs/rules/prefer-string-starts-ends-with.md @@ -7,18 +7,19 @@ description: 'Enforce using `String#startsWith` and `String#endsWith` over other > See **https://typescript-eslint.io/rules/prefer-string-starts-ends-with** for documentation. There are multiple ways to verify if a string starts or ends with a specific string, such as `foo.indexOf('bar') === 0`. -Since ES2015 has added `String#startsWith` and `String#endsWith`, this rule reports other ways to be consistent. +As of ES2015, the most common way in JavaScript is to use `String#startsWith` and `String#endsWith`. +Keeping to those methods consistently helps with code readability. -## Examples +This rule reports when a string method can be replaced safely with `String#startsWith` or `String#endsWith`. -This rule is aimed at enforcing a consistent way to check whether a string starts or ends with a specific string. +## Examples ### ❌ Incorrect ```ts -let foo: string; +declare const foo: string; // starts with foo[0] === 'b'; @@ -42,7 +43,12 @@ foo.match(/bar$/) != null; ### ✅ Correct ```ts +declare const foo: string; + +// starts with foo.startsWith('bar'); + +// ends with foo.endsWith('bar'); ``` diff --git a/packages/eslint-plugin/docs/rules/prefer-ts-expect-error.md b/packages/eslint-plugin/docs/rules/prefer-ts-expect-error.md index 7fb2188472c8..8cc2abb23055 100644 --- a/packages/eslint-plugin/docs/rules/prefer-ts-expect-error.md +++ b/packages/eslint-plugin/docs/rules/prefer-ts-expect-error.md @@ -6,19 +6,15 @@ description: 'Enforce using `@ts-expect-error` over `@ts-ignore`.' > > See **https://typescript-eslint.io/rules/prefer-ts-expect-error** for documentation. -TypeScript allows you to suppress all errors on a line by placing a single-line comment or a comment block line starting with `@ts-ignore` immediately before the erroring line. -While powerful, there is no way to know if a `@ts-ignore` is actually suppressing an error without manually investigating what happens when the `@ts-ignore` is removed. +TypeScript allows you to suppress all errors on a line by placing a comment starting with `@ts-ignore` or `@ts-expect-error` immediately before the erroring line. +The two directives work the same, except `@ts-expect-error` causes a type error if placed before a line that's not erroring in the first place. This means its easy for `@ts-ignore`s to be forgotten about, and remain in code even after the error they were suppressing is fixed. This is dangerous, as if a new error arises on that line it'll be suppressed by the forgotten about `@ts-ignore`, and so be missed. -To address this, TS3.9 ships with a new single-line comment directive: `// @ts-expect-error`. - -This directive operates in the same manner as `@ts-ignore`, but will error if the line it's meant to be suppressing doesn't actually contain an error, making it a lot safer. - ## Examples -This rule looks for usages of `@ts-ignore`, and flags them to be replaced with `@ts-expect-error`. +This rule reports any usage of `@ts-ignore`, including a fixer to replace with `@ts-expect-error`. @@ -66,7 +62,7 @@ const isOptionEnabled = (key: string): boolean => { ## When Not To Use It -If you are **NOT** using TypeScript 3.9 (or greater), then you will not be able to use this rule, as the directive is not supported +If you are compiling against multiple versions of TypeScript and using `@ts-ignore` to ignore version-specific type errors, this rule might get in your way. ## Further Reading diff --git a/packages/eslint-plugin/docs/rules/require-array-sort-compare.md b/packages/eslint-plugin/docs/rules/require-array-sort-compare.md index ad5ebc20e476..66b39a004cd0 100644 --- a/packages/eslint-plugin/docs/rules/require-array-sort-compare.md +++ b/packages/eslint-plugin/docs/rules/require-array-sort-compare.md @@ -6,23 +6,16 @@ description: 'Require `Array#sort` calls to always provide a `compareFunction`.' > > See **https://typescript-eslint.io/rules/require-array-sort-compare** for documentation. -This rule prevents invoking the `Array#sort()` method without providing a `compare` argument. -When called without a compare function, `Array#sort()` converts all non-undefined array elements into strings and then compares said strings based off their UTF-16 code units. +When called without a compare function, `Array#sort()` converts all non-undefined array elements into strings and then compares said strings based off their UTF-16 code units [[ECMA specification](https://www.ecma-international.org/ecma-262/9.0/#sec-sortcompare)]. The result is that elements are sorted alphabetically, regardless of their type. -When sorting numbers, this results in the classic "10 before 2" order: +For example, when sorting numbers, this results in a "10 before 2" order: ```ts [1, 2, 3, 10, 20, 30].sort(); //→ [1, 10, 2, 20, 3, 30] ``` -This also means that `Array#sort` does not always sort consistently, as elements may have custom `#toString` implementations that are not deterministic; this trap is noted in the language specification thusly: - -:::note -Method calls performed by the `ToString` abstract operations in steps 5 and 7 have the potential to cause `SortCompare` to not behave as a consistent comparison function. - -https://www.ecma-international.org/ecma-262/9.0/#sec-sortcompare -::: +This rule reports on any call to the `Array#sort()` method that doesn't provide a `compare` argument. ## Examples @@ -82,4 +75,4 @@ const three = '3'; ## When Not To Use It -If you understand the language specification enough, you can turn this rule off safely. +If you understand the language specification enough, and/or only ever sort arrays in a string-like manner, you can turn this rule off safely. diff --git a/packages/eslint-plugin/docs/rules/restrict-plus-operands.md b/packages/eslint-plugin/docs/rules/restrict-plus-operands.md index 4969c57b0d18..fc823f6da9f8 100644 --- a/packages/eslint-plugin/docs/rules/restrict-plus-operands.md +++ b/packages/eslint-plugin/docs/rules/restrict-plus-operands.md @@ -1,11 +1,16 @@ --- -description: 'Require both operands of addition to have type `number` or `string`.' +description: 'Require both operands of addition to be the same type and be `bigint`, `number`, or `string`.' --- > 🛑 This file is source code, not the primary documentation location! 🛑 > > See **https://typescript-eslint.io/rules/restrict-plus-operands** for documentation. +TypeScript allows `+` adding together two values of any type(s). +However, adding values that are not the same type and/or are not the same primitive type is often a sign of programmer error. + +This rule reports when a `+` operation combines two values of different types, or a type that is not `bigint`, `number`, or `string`. + ## Examples @@ -79,4 +84,15 @@ var fn = (a: any, b: bigint) => a + b; var fn = (a: any, b: number) => a + b; ``` -## How to Use +## When Not To Use It + +If you don't mind `"[object Object]"` in your strings, then you will not need this rule. + +## Related To + +- [`no-base-to-string`](./no-base-to-string.md) +- [`restrict-template-expressions`](./restrict-template-expressions.md) + +## Further Reading + +- [`Object.prototype.toString()` MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString) diff --git a/packages/eslint-plugin/docs/rules/restrict-template-expressions.md b/packages/eslint-plugin/docs/rules/restrict-template-expressions.md index c3309a559669..e2d18d8e267f 100644 --- a/packages/eslint-plugin/docs/rules/restrict-template-expressions.md +++ b/packages/eslint-plugin/docs/rules/restrict-template-expressions.md @@ -6,6 +6,10 @@ description: 'Enforce template literal expressions to be of `string` type.' > > See **https://typescript-eslint.io/rules/restrict-template-expressions** for documentation. +JavaScript will call `toString()` on an object when it is converted to a string, such as when `+` adding to a string or in `${}` template literals. +The default Object `.toString()` returns `"[object Object]"`, which is often not what was intended. +This rule reports on values used in a template literal string that aren't primitives and don't define a more useful `.toString()` method. + ## Examples @@ -85,3 +89,8 @@ const msg1 = `arg = ${arg}`; const arg = /foo/; const msg1 = `arg = ${arg}`; ``` + +## Related To + +- [`no-base-to-string`](./no-base-to-string.md) +- [`restrict-plus-operands`](./restrict-plus-operands.md) diff --git a/packages/eslint-plugin/docs/rules/sort-type-union-intersection-members.md b/packages/eslint-plugin/docs/rules/sort-type-union-intersection-members.md index ae85e0c98065..2a47547219bf 100644 --- a/packages/eslint-plugin/docs/rules/sort-type-union-intersection-members.md +++ b/packages/eslint-plugin/docs/rules/sort-type-union-intersection-members.md @@ -12,22 +12,11 @@ Sorting union (`|`) and intersection (`&`) types can help: - find repeated types - reduce diff churn -## Examples +This rule reports on any types that aren't sorted alphabetically. -Sorting within each group is done using the following code: +> Types are sorted case-insensitively and treating numbers like a human would, falling back to character code sorting in case of ties. -```ts -const collator = new Intl.Collator('en', { - sensitivity: 'base', - numeric: true, -}); - -function compare(a, b) { - return collator.compare(a, b) || (a < b ? -1 : a > b ? 1 : 0); -} -``` - -In other words, the types are sorted alphabetically, case-insensitively and treating numbers like a human would, falling back to character code sorting in case of ties. +## Examples diff --git a/packages/eslint-plugin/docs/rules/switch-exhaustiveness-check.md b/packages/eslint-plugin/docs/rules/switch-exhaustiveness-check.md index a3300d406021..9320624924b9 100644 --- a/packages/eslint-plugin/docs/rules/switch-exhaustiveness-check.md +++ b/packages/eslint-plugin/docs/rules/switch-exhaustiveness-check.md @@ -6,7 +6,10 @@ description: 'Require switch-case statements to be exhaustive with union type.' > > See **https://typescript-eslint.io/rules/switch-exhaustiveness-check** for documentation. -Union type may have a lot of parts. It's easy to forget to consider all cases in switch. This rule reminds which parts are missing. If domain of the problem requires to have only a partial switch, developer may _explicitly_ add a default clause. +When working with union types in TypeScript, it's common to want to write a `switch` statement intended to contain a `case` for each constituent (possible type in the union). +However, if the union type changes, it's easy to forget to modify the cases to account for any new types. + +This rule reports when a `switch` statement over a value typed as a union of literals is missing a case for any of those literal types and does not have a `default` clause. ## Examples @@ -28,10 +31,9 @@ const day = 'Monday' as Day; let result = 0; switch (day) { - case 'Monday': { + case 'Monday': result = 1; break; - } } ``` @@ -51,34 +53,27 @@ const day = 'Monday' as Day; let result = 0; switch (day) { - case 'Monday': { + case 'Monday': result = 1; break; - } - case 'Tuesday': { + case 'Tuesday': result = 2; break; - } - case 'Wednesday': { + case 'Wednesday': result = 3; break; - } - case 'Thursday': { + case 'Thursday': result = 4; break; - } - case 'Friday': { + case 'Friday': result = 5; break; - } - case 'Saturday': { + case 'Saturday': result = 6; break; - } - case 'Sunday': { + case 'Sunday': result = 7; break; - } } ``` @@ -98,16 +93,14 @@ const day = 'Monday' as Day; let result = 0; switch (day) { - case 'Monday': { + case 'Monday': result = 1; break; - } - default: { + default: result = 42; - } } ``` ## When Not To Use It -If program doesn't have union types with many parts. Downside of this rule is the need for type information, so it's slower than regular rules. +If you don't frequently `switch` over union types with many parts, or intentionally wish to leave out some parts. diff --git a/packages/eslint-plugin/docs/rules/triple-slash-reference.md b/packages/eslint-plugin/docs/rules/triple-slash-reference.md index c9bd861a4362..f48f7c98497b 100644 --- a/packages/eslint-plugin/docs/rules/triple-slash-reference.md +++ b/packages/eslint-plugin/docs/rules/triple-slash-reference.md @@ -6,9 +6,11 @@ description: 'Disallow certain triple slash directives in favor of ES6-style imp > > See **https://typescript-eslint.io/rules/triple-slash-reference** for documentation. -## Examples +TypeScript's `///` triple-slash references are a way to indicate that types from another module are available in a file. +Use of triple-slash reference type directives is generally discouraged in favor of ECMAScript Module `import`s. +This rule reports on the use of `/// `, `/// `, or `/// ` directives. -Use of triple-slash reference type directives is discouraged in favor of the newer `import` style. This rule allows you to ban use of `/// `, `/// `, or `/// ` directives. +## Examples ## Options diff --git a/packages/eslint-plugin/docs/rules/typedef.md b/packages/eslint-plugin/docs/rules/typedef.md index 3e1e2f6459ec..11e2b39c4405 100644 --- a/packages/eslint-plugin/docs/rules/typedef.md +++ b/packages/eslint-plugin/docs/rules/typedef.md @@ -9,6 +9,9 @@ description: 'Require type annotations in certain places.' TypeScript cannot always infer types for all places in code. Some locations require type annotations for their types to be inferred. +This rule can enforce type annotations in locations regardless of whether they're required. +This is typically used to maintain consistency for element types that sometimes require them. + ```ts class ContainsText { // There must be a type annotation here to infer the type @@ -22,6 +25,8 @@ class ContainsText { } ``` +> To enforce type definitions existing on call signatures, use [`explicit-function-return-type`](./explicit-function-return-type.md), or [`explicit-module-boundary-types`](./explicit-module-boundary-types.md). + :::caution Requiring type annotations unnecessarily can be cumbersome to maintain and generally reduces code readability. @@ -31,13 +36,6 @@ TypeScript is often better at inferring types than easily written type annotatio ::: -## Examples - -This rule can enforce type annotations in locations regardless of whether they're required. -This is typically used to maintain consistency for element types that sometimes require them. - -> To enforce type definitions existing on call signatures, use `explicit-function-return-type`, or `explicit-module-boundary-types`. - ## Options For example, with the following configuration: diff --git a/packages/eslint-plugin/docs/rules/unbound-method.md b/packages/eslint-plugin/docs/rules/unbound-method.md index 091780dcb6c4..99dc8ba79632 100644 --- a/packages/eslint-plugin/docs/rules/unbound-method.md +++ b/packages/eslint-plugin/docs/rules/unbound-method.md @@ -6,15 +6,18 @@ description: 'Enforce unbound methods are called with their expected scope.' > > See **https://typescript-eslint.io/rules/unbound-method** for documentation. -Class functions don't preserve the class scope when passed as standalone variables. +Class method functions don't preserve the class scope when passed as standalone variables ("unbound"). If your function does not access `this`, [you can annotate it with `this: void`](https://www.typescriptlang.org/docs/handbook/2/functions.html#declaring-this-in-a-function), or consider using an arrow function instead. +Otherwise, passing class methods around as values can remove type safety by failing to capture `this`. +This rule reports when a class method is referenced in an unbound manner. + +:::note Tip If you're working with `jest`, you can use [`eslint-plugin-jest`'s version of this rule](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/unbound-method.md) to lint your test files, which knows when it's ok to pass an unbound method to `expect` calls. +::: ## Examples -Examples of code for this rule with the default options: - ### ❌ Incorrect diff --git a/packages/eslint-plugin/docs/rules/unified-signatures.md b/packages/eslint-plugin/docs/rules/unified-signatures.md index b4b178d3df3e..5736561d2ff4 100644 --- a/packages/eslint-plugin/docs/rules/unified-signatures.md +++ b/packages/eslint-plugin/docs/rules/unified-signatures.md @@ -6,11 +6,13 @@ description: 'Disallow two overloads that could be unified into one with a union > > See **https://typescript-eslint.io/rules/unified-signatures** for documentation. -## Examples +Function overload signatures are a TypeScript way to define a function that can be called in multiple very different ways. +Overload signatures add syntax and theoretical bloat, so it's generally best to avoid using them when possible. +Switching to union types and/or optional or rest parameters can often avoid the need for overload signatures. -This rule aims to keep the source code as maintainable as possible by reducing the amount of overloads. +This rule reports when function overload signatures can be replaced by a single function signature. -Examples of code for this rule with the default options: +## Examples diff --git a/packages/eslint-plugin/src/rules/no-namespace.ts b/packages/eslint-plugin/src/rules/no-namespace.ts index ee986a4d82d4..2a9a4a251bed 100644 --- a/packages/eslint-plugin/src/rules/no-namespace.ts +++ b/packages/eslint-plugin/src/rules/no-namespace.ts @@ -16,12 +16,12 @@ export default util.createRule({ meta: { type: 'suggestion', docs: { - description: 'Disallow custom TypeScript modules and namespaces', + description: 'Disallow TypeScript namespaces', recommended: 'error', }, messages: { moduleSyntaxIsPreferred: - 'ES2015 module syntax is preferred over custom TypeScript modules and namespaces.', + 'ES2015 module syntax is preferred over namespaces.', }, schema: [ { diff --git a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts index a4cc0374395e..ad5d0a832b75 100644 --- a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts +++ b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts @@ -22,7 +22,7 @@ export default util.createRule({ type: 'problem', docs: { description: - 'Require both operands of addition to have type `number` or `string`', + 'Require both operands of addition to be the same type and be `bigint`, `number`, or `string`', recommended: 'error', requiresTypeChecking: true, }, diff --git a/packages/website/plugins/generated-rule-docs.ts b/packages/website/plugins/generated-rule-docs.ts index 020ac5f74a82..a05519ab7da6 100644 --- a/packages/website/plugins/generated-rule-docs.ts +++ b/packages/website/plugins/generated-rule-docs.ts @@ -52,20 +52,26 @@ export const generatedRuleDocs: Plugin = () => { ); // 2. Add a description of the rule at the top of the file - root.children.unshift({ - children: [ - { - children: meta.docs.description - .split(/`(.+?)`/) - .map((value, index, array) => ({ - type: index % 2 === 0 ? 'text' : 'inlineCode', - value: index === array.length - 1 ? `${value}.` : value, - })), - type: 'paragraph', - }, - ], - type: 'blockquote', - } as mdast.Blockquote); + root.children.unshift( + { + children: [ + { + children: meta.docs.description + .split(/`(.+?)`/) + .map((value, index, array) => ({ + type: index % 2 === 0 ? 'text' : 'inlineCode', + value: index === array.length - 1 ? `${value}.` : value, + })), + type: 'paragraph', + }, + ], + type: 'blockquote', + } as mdast.Blockquote, + { + type: 'jsx', + value: ``, + } as unist.Node, + ); // 3. Add a notice about formatting rules being 🤢 if (meta.type === 'layout') { @@ -82,19 +88,7 @@ export const generatedRuleDocs: Plugin = () => { root.children.unshift(warningNode); } - // 4. Add a rule attributes list before the first h2. - const attributesH2Index = root.children.findIndex( - child => nodeIsHeading(child) && child.depth === 2, - ); - - // The actual content will be injected on client side. - const attributesNode = { - type: 'jsx', - value: ``, - }; - root.children.splice(attributesH2Index, 0, attributesNode); - - // 5. Make sure the appropriate headers exist to place content under + // 4. Make sure the appropriate headers exist to place content under const [howToUseH2Index, optionsH2Index] = ((): [number, number] => { let howToUseH2Index = root.children.findIndex( createH2TextFilter('How to Use'), @@ -162,7 +156,7 @@ export const generatedRuleDocs: Plugin = () => { return [howToUseH2Index, optionsH2Index]; })(); - // 6. Add a description of how to use / options for the rule + // 5. Add a description of how to use / options for the rule const optionLevel = meta.docs.recommended === 'error' ? 'error' : 'warn'; if (meta.docs.extendsBaseRule) { @@ -210,7 +204,12 @@ export const generatedRuleDocs: Plugin = () => { };`, } as mdast.Code); } else { - root.children.splice(attributesH2Index + 1, 0, { + // For non-extended rules, the code snippet is placed before the first h2 + // (i.e. at the end of the initial explanation) + const firstH2Index = root.children.findIndex( + child => nodeIsHeading(child) && child.depth === 2, + ); + root.children.splice(firstH2Index, 0, { lang: 'js', type: 'code', meta: 'title=".eslintrc.cjs"', @@ -297,7 +296,7 @@ export const generatedRuleDocs: Plugin = () => { } } - // 7. Add a notice about coming from ESLint core for extension rules + // 6. Add a notice about coming from ESLint core for extension rules if (meta.docs.extendsBaseRule) { root.children.push({ children: [ @@ -329,7 +328,7 @@ export const generatedRuleDocs: Plugin = () => { } as mdast.Paragraph); } - // 8. Also add a link to view the rule's source and test code + // 7. Also add a link to view the rule's source and test code root.children.push( { children: [ diff --git a/packages/website/src/theme/MDXComponents/Feature.module.css b/packages/website/src/theme/MDXComponents/Feature.module.css index ac65c0a1d977..aeef8f51e0a2 100644 --- a/packages/website/src/theme/MDXComponents/Feature.module.css +++ b/packages/website/src/theme/MDXComponents/Feature.module.css @@ -4,10 +4,13 @@ box-shadow: var(--ifm-global-shadow-lw); color: var(--token-color) !important; display: flex; + flex-basis: 30%; + flex-grow: 1; + flex-shrink: 3; font-size: 0.8rem; margin: 0 0 1rem; + min-width: 15rem; padding: 0.75rem 1rem; - width: 100%; } .emoji { @@ -17,7 +20,3 @@ .children { margin: 0; } - -.feature + .feature { - margin-left: 1rem; -} diff --git a/packages/website/src/theme/MDXComponents/Feature.tsx b/packages/website/src/theme/MDXComponents/Feature.tsx index 157f0949a31c..64aac69a68ed 100644 --- a/packages/website/src/theme/MDXComponents/Feature.tsx +++ b/packages/website/src/theme/MDXComponents/Feature.tsx @@ -1,4 +1,3 @@ -import clsx from 'clsx'; import React from 'react'; import styles from './Feature.module.css'; @@ -6,16 +5,11 @@ import styles from './Feature.module.css'; export interface FeatureProps { children: React.ReactNode; emoji: string; - fullWidth?: boolean; } -export function Feature({ - children, - emoji, - fullWidth, -}: FeatureProps): JSX.Element { +export function Feature({ children, emoji }: FeatureProps): JSX.Element { return ( -
    +
    {emoji}

    {children}

    diff --git a/packages/website/src/theme/MDXComponents/RuleAttributes.module.css b/packages/website/src/theme/MDXComponents/RuleAttributes.module.css index 87c45721e1d3..bd8bc627c3b3 100644 --- a/packages/website/src/theme/MDXComponents/RuleAttributes.module.css +++ b/packages/website/src/theme/MDXComponents/RuleAttributes.module.css @@ -1,3 +1,9 @@ .features { display: flex; + gap: 0 1rem; + flex-wrap: wrap; +} + +.features + h2 { + margin-top: 1rem; } diff --git a/packages/website/src/theme/MDXComponents/RuleAttributes.tsx b/packages/website/src/theme/MDXComponents/RuleAttributes.tsx index bd98fbcb4272..fec80e87d7a2 100644 --- a/packages/website/src/theme/MDXComponents/RuleAttributes.tsx +++ b/packages/website/src/theme/MDXComponents/RuleAttributes.tsx @@ -28,15 +28,23 @@ export function RuleAttributes({ name }: { name: string }): React.ReactNode { features.push({ children: ( <> - Extend{' '} - - "plugin:@typescript-eslint/{recommendation}" - {' '} + Extending{' '} + + + "plugin:@typescript-eslint/{recommendation}" + + {' '} in an{' '} - - ESLint configuration file + + ESLint configuration {' '} - to enable this rule. + enables this rule. ), emoji, @@ -49,7 +57,10 @@ export function RuleAttributes({ name }: { name: string }): React.ReactNode { <> Some problems reported by this rule are automatically fixable by the{' '} --fix{' '} - + ESLint command line option . @@ -64,7 +75,10 @@ export function RuleAttributes({ name }: { name: string }): React.ReactNode { children: ( <> Some problems reported by this rule are manually fixable by editor{' '} - + suggestions . @@ -79,7 +93,10 @@ export function RuleAttributes({ name }: { name: string }): React.ReactNode { children: ( <> This rule requires{' '} - type information to run. + + type information + {' '} + to run. ), emoji: '💭', From 28cfaff8b4c414b05f5f8dcc84a162505e5e1edf Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 1 Oct 2022 01:14:18 -0400 Subject: [PATCH 05/14] Fix lint:markdown --- .../eslint-plugin/docs/rules/prefer-literal-enum-member.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/prefer-literal-enum-member.md b/packages/eslint-plugin/docs/rules/prefer-literal-enum-member.md index 6d9017e761b7..2c0bd40a33de 100644 --- a/packages/eslint-plugin/docs/rules/prefer-literal-enum-member.md +++ b/packages/eslint-plugin/docs/rules/prefer-literal-enum-member.md @@ -67,7 +67,7 @@ Examples of code for the `{ "allowBitwiseExpressions": true }` option: -#### ❌ Incorrect +### ❌ Incorrect ```ts const x = 1; @@ -82,7 +82,7 @@ enum Foo { } ``` -#### ✅ Correct +### ✅ Correct ```ts enum Foo { From 98150359e7e318c6d19012f634ac2474c46ab5b7 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 1 Oct 2022 01:22:10 -0400 Subject: [PATCH 06/14] Undo extension rule description nitpicking --- .../04-enhancement-new-base-rule-extension.yaml | 5 ++--- packages/eslint-plugin/docs/rules/README.md | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/04-enhancement-new-base-rule-extension.yaml b/.github/ISSUE_TEMPLATE/04-enhancement-new-base-rule-extension.yaml index ffe35dd058b5..1c02ebe658a4 100644 --- a/.github/ISSUE_TEMPLATE/04-enhancement-new-base-rule-extension.yaml +++ b/.github/ISSUE_TEMPLATE/04-enhancement-new-base-rule-extension.yaml @@ -11,9 +11,8 @@ body: attributes: value: | # What is a "Base Rule Extension"? - In some cases, ESLint provides a rule itself, but it doesn't support TypeScript syntax. - It may crash, or it ignore the syntax, or falsely reports against it. - In these cases we create what we call an extension rule: a rule within our plugin that has the same functionality, but also supports TypeScript. + In some cases, ESLint provides a rule itself, but it doesn't support TypeScript syntax; either it crashes, or it ignores the syntax, or it falsely reports against it. + In these cases, we create what we call an extension rule; a rule within our plugin that has the same functionality, but also supports TypeScript. - type: checkboxes id: sanity-checks attributes: diff --git a/packages/eslint-plugin/docs/rules/README.md b/packages/eslint-plugin/docs/rules/README.md index 937c5cab2692..7c6bd00d36df 100644 --- a/packages/eslint-plugin/docs/rules/README.md +++ b/packages/eslint-plugin/docs/rules/README.md @@ -17,8 +17,7 @@ import RulesTable from "@site/src/components/RulesTable"; ## Extension Rules -In some cases, ESLint provides a rule itself, but it doesn't support TypeScript syntax. -It may crash, or it ignore the syntax, or falsely reports against it. -In these cases we create what we call an extension rule: a rule within our plugin that has the same functionality, but also supports TypeScript. +In some cases, ESLint provides a rule itself, but it doesn't support TypeScript syntax; either it crashes, or it ignores the syntax, or it falsely reports against it. +In these cases, we create what we call an extension rule; a rule within our plugin that has the same functionality, but also supports TypeScript. From 90d8418c356e41010f3ae54cc18e1c52a002db66 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 1 Oct 2022 01:39:58 -0400 Subject: [PATCH 07/14] Remove rule attributes and other change --- packages/website/docusaurusConfig.ts | 2 +- .../website/plugins/generated-rule-docs.ts | 61 +++---- .../theme/MDXComponents/Feature.module.css | 22 --- .../src/theme/MDXComponents/Feature.tsx | 17 -- .../MDXComponents/RuleAttributes.module.css | 10 +- .../theme/MDXComponents/RuleAttributes.tsx | 162 +++++++----------- 6 files changed, 97 insertions(+), 177 deletions(-) delete mode 100644 packages/website/src/theme/MDXComponents/Feature.module.css delete mode 100644 packages/website/src/theme/MDXComponents/Feature.tsx diff --git a/packages/website/docusaurusConfig.ts b/packages/website/docusaurusConfig.ts index 4bc2a650ad90..1a9a41e548e0 100644 --- a/packages/website/docusaurusConfig.ts +++ b/packages/website/docusaurusConfig.ts @@ -141,7 +141,7 @@ const themeConfig: ThemeCommonConfig & AlgoliaThemeConfig = { }, ], // style: 'primary', - copyright: `Copyright © ${new Date().getFullYear()} TypeScript ESLint, Inc. Built with Docusaurus.`, + copyright: `Copyright © ${new Date().getFullYear()} TypeScript ESLint, Inc. Built with Docusaurus.`, }, prism: { theme: { diff --git a/packages/website/plugins/generated-rule-docs.ts b/packages/website/plugins/generated-rule-docs.ts index a05519ab7da6..e21a408dbf42 100644 --- a/packages/website/plugins/generated-rule-docs.ts +++ b/packages/website/plugins/generated-rule-docs.ts @@ -52,26 +52,20 @@ export const generatedRuleDocs: Plugin = () => { ); // 2. Add a description of the rule at the top of the file - root.children.unshift( - { - children: [ - { - children: meta.docs.description - .split(/`(.+?)`/) - .map((value, index, array) => ({ - type: index % 2 === 0 ? 'text' : 'inlineCode', - value: index === array.length - 1 ? `${value}.` : value, - })), - type: 'paragraph', - }, - ], - type: 'blockquote', - } as mdast.Blockquote, - { - type: 'jsx', - value: ``, - } as unist.Node, - ); + root.children.unshift({ + children: [ + { + children: meta.docs.description + .split(/`(.+?)`/) + .map((value, index, array) => ({ + type: index % 2 === 0 ? 'text' : 'inlineCode', + value: index === array.length - 1 ? `${value}.` : value, + })), + type: 'paragraph', + }, + ], + type: 'blockquote', + } as mdast.Blockquote); // 3. Add a notice about formatting rules being 🤢 if (meta.type === 'layout') { @@ -88,7 +82,19 @@ export const generatedRuleDocs: Plugin = () => { root.children.unshift(warningNode); } - // 4. Make sure the appropriate headers exist to place content under + // 4. Add a rule attributes list before the first h2. + const attributesH2Index = root.children.findIndex( + child => nodeIsHeading(child) && child.depth === 2, + ); + + // The actual content will be injected on client side. + const attributesNode = { + type: 'jsx', + value: ``, + }; + root.children.splice(attributesH2Index, 0, attributesNode); + + // 5. Make sure the appropriate headers exist to place content under const [howToUseH2Index, optionsH2Index] = ((): [number, number] => { let howToUseH2Index = root.children.findIndex( createH2TextFilter('How to Use'), @@ -156,7 +162,7 @@ export const generatedRuleDocs: Plugin = () => { return [howToUseH2Index, optionsH2Index]; })(); - // 5. Add a description of how to use / options for the rule + // 6. Add a description of how to use / options for the rule const optionLevel = meta.docs.recommended === 'error' ? 'error' : 'warn'; if (meta.docs.extendsBaseRule) { @@ -204,12 +210,7 @@ export const generatedRuleDocs: Plugin = () => { };`, } as mdast.Code); } else { - // For non-extended rules, the code snippet is placed before the first h2 - // (i.e. at the end of the initial explanation) - const firstH2Index = root.children.findIndex( - child => nodeIsHeading(child) && child.depth === 2, - ); - root.children.splice(firstH2Index, 0, { + root.children.splice(optionsH2Index, 0, { lang: 'js', type: 'code', meta: 'title=".eslintrc.cjs"', @@ -296,7 +297,7 @@ export const generatedRuleDocs: Plugin = () => { } } - // 6. Add a notice about coming from ESLint core for extension rules + // 7. Add a notice about coming from ESLint core for extension rules if (meta.docs.extendsBaseRule) { root.children.push({ children: [ @@ -328,7 +329,7 @@ export const generatedRuleDocs: Plugin = () => { } as mdast.Paragraph); } - // 7. Also add a link to view the rule's source and test code + // 8. Also add a link to view the rule's source and test code root.children.push( { children: [ diff --git a/packages/website/src/theme/MDXComponents/Feature.module.css b/packages/website/src/theme/MDXComponents/Feature.module.css deleted file mode 100644 index aeef8f51e0a2..000000000000 --- a/packages/website/src/theme/MDXComponents/Feature.module.css +++ /dev/null @@ -1,22 +0,0 @@ -.feature { - background-color: var(--token-background); - border-radius: var(--ifm-code-border-radius); - box-shadow: var(--ifm-global-shadow-lw); - color: var(--token-color) !important; - display: flex; - flex-basis: 30%; - flex-grow: 1; - flex-shrink: 3; - font-size: 0.8rem; - margin: 0 0 1rem; - min-width: 15rem; - padding: 0.75rem 1rem; -} - -.emoji { - margin-right: 0.5rem; -} - -.children { - margin: 0; -} diff --git a/packages/website/src/theme/MDXComponents/Feature.tsx b/packages/website/src/theme/MDXComponents/Feature.tsx deleted file mode 100644 index 64aac69a68ed..000000000000 --- a/packages/website/src/theme/MDXComponents/Feature.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; - -import styles from './Feature.module.css'; - -export interface FeatureProps { - children: React.ReactNode; - emoji: string; -} - -export function Feature({ children, emoji }: FeatureProps): JSX.Element { - return ( -
    -
    {emoji}
    -

    {children}

    -
    - ); -} diff --git a/packages/website/src/theme/MDXComponents/RuleAttributes.module.css b/packages/website/src/theme/MDXComponents/RuleAttributes.module.css index bd8bc627c3b3..97c07287baba 100644 --- a/packages/website/src/theme/MDXComponents/RuleAttributes.module.css +++ b/packages/website/src/theme/MDXComponents/RuleAttributes.module.css @@ -1,9 +1,7 @@ -.features { - display: flex; - gap: 0 1rem; - flex-wrap: wrap; +.taskList { + list-style: none; } -.features + h2 { - margin-top: 1rem; +:not(.taskList > li) > .taskList { + padding-left: 0; } diff --git a/packages/website/src/theme/MDXComponents/RuleAttributes.tsx b/packages/website/src/theme/MDXComponents/RuleAttributes.tsx index fec80e87d7a2..4248270628da 100644 --- a/packages/website/src/theme/MDXComponents/RuleAttributes.tsx +++ b/packages/website/src/theme/MDXComponents/RuleAttributes.tsx @@ -1,113 +1,73 @@ -import type { RuleMetaDataDocs } from '@site/../utils/dist/ts-eslint/Rule'; import { useRulesMeta } from '@site/src/hooks/useRulesMeta'; +import type { TSESLint } from '@typescript-eslint/utils'; import React from 'react'; -import type { FeatureProps } from './Feature'; -import { Feature } from './Feature'; import styles from './RuleAttributes.module.css'; -const getRecommendation = (docs: RuleMetaDataDocs): [string, string] => { - return docs.recommended === 'strict' - ? ['🔒', 'strict'] - : docs.requiresTypeChecking - ? ['🧠', 'recommended-requiring-type-checking'] - : ['✅', 'recommended']; -}; - -export function RuleAttributes({ name }: { name: string }): React.ReactNode { +export function RuleAttributes({ name }: { name: string }): JSX.Element | null { const rules = useRulesMeta(); const rule = rules.find(rule => rule.name === name); - if (!rule?.docs) { + if (!rule) { return null; } - - const features: FeatureProps[] = []; - - if (rule.docs.recommended) { - const [emoji, recommendation] = getRecommendation(rule.docs); - features.push({ - children: ( - <> - Extending{' '} - - - "plugin:@typescript-eslint/{recommendation}" - - {' '} - in an{' '} - - ESLint configuration - {' '} - enables this rule. - - ), - emoji, - }); - } - - if (rule.fixable) { - features.push({ - children: ( - <> - Some problems reported by this rule are automatically fixable by the{' '} - --fix{' '} - - ESLint command line option - - . - - ), - emoji: '🛠', - }); - } - - if (rule.hasSuggestions) { - features.push({ - children: ( - <> - Some problems reported by this rule are manually fixable by editor{' '} - - suggestions - - . - - ), - emoji: '💡', - }); - } - - if (rule.docs.requiresTypeChecking) { - features.push({ - children: ( - <> - This rule requires{' '} - - type information - {' '} - to run. - - ), - emoji: '💭', - }); - } - return ( -
    - {features.map(feature => ( - - ))} -
    + <> +

    Attributes

    +
      +
    • + + Included in configs +
        +
      • + + ✅ Recommended +
      • +
      • + + 🔒 Strict +
      • +
      +
    • +
    • + + Fixable +
        +
      • + + 🔧 Automated Fixer +
      • +
      • + + 💡 Suggestion Fixer +
      • +
      +
    • +
    • + + 💭 Requires type information +
    • +
    + ); } From d0edd02198f80c1c63934a99d3e10bec02879151 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 1 Oct 2022 01:44:41 -0400 Subject: [PATCH 08/14] Remove border-color --- packages/website/src/css/custom.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/website/src/css/custom.css b/packages/website/src/css/custom.css index 9c039bdc6f59..73d46606cb50 100644 --- a/packages/website/src/css/custom.css +++ b/packages/website/src/css/custom.css @@ -62,8 +62,6 @@ html[data-theme='dark']:root { --docsearch-muted-color: #aaa; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); - - --gray-border-shadow: var(--ifm-color-secondary-dark); } .header-github-link:hover { From 80ff196f1658fc07d55636ffb34da0cd0091942d Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 1 Oct 2022 01:52:43 -0400 Subject: [PATCH 09/14] codebasez --- .../eslint-plugin/docs/rules/explicit-member-accessibility.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md b/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md index 2a300704db7b..87d7d23b0381 100644 --- a/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md +++ b/packages/eslint-plugin/docs/rules/explicit-member-accessibility.md @@ -22,7 +22,7 @@ which properties. ## Options -### Configuring in a mixed JS/TS codebasez +### Configuring in a mixed JS/TS codebase If you are working on a codebase within which you lint non-TypeScript code (i.e. `.js`/`.mjs`/`.cjs`/`.jsx`), you should ensure that you should use [ESLint `overrides`](https://eslint.org/docs/user-guide/configuring#disabling-rules-only-for-a-group-of-files) to only enable the rule on `.ts`/`.mts`/`.cts`/`.tsx` files. If you don't, then you will get unfixable lint errors reported within `.js`/`.mjs`/`.cjs`/`.jsx` files. From b4f823173cb5291721681028c1a6fbdb6debeb87 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 1 Oct 2022 02:04:09 -0400 Subject: [PATCH 10/14] Split out comma-spacing --- packages/eslint-plugin/src/rules/comma-spacing.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/comma-spacing.ts b/packages/eslint-plugin/src/rules/comma-spacing.ts index fda50d1b2e4a..5538fffe4a51 100644 --- a/packages/eslint-plugin/src/rules/comma-spacing.ts +++ b/packages/eslint-plugin/src/rules/comma-spacing.ts @@ -19,7 +19,7 @@ type MessageIds = 'unexpected' | 'missing'; export default createRule({ name: 'comma-spacing', meta: { - type: 'layout', + type: 'suggestion', docs: { description: 'Enforce consistent spacing before and after commas', recommended: false, From 59ad285d027ca0a4374954b9e988b6988e73b16c Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 1 Oct 2022 02:12:48 -0400 Subject: [PATCH 11/14] Remove sidebar.rules.js --- packages/website/sidebars/sidebar.rules.js | 26 ++++++++-------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/packages/website/sidebars/sidebar.rules.js b/packages/website/sidebars/sidebar.rules.js index e698d7cda05c..b50758724110 100644 --- a/packages/website/sidebars/sidebar.rules.js +++ b/packages/website/sidebars/sidebar.rules.js @@ -13,19 +13,14 @@ const rules = Object.entries(plugin.rules).map(([name, rule]) => { const deprecatedRules = new Set(rules.filter(rule => rule.meta.deprecated)); const formattingRules = new Set( - rules.filter(rule => !rule.meta.deprecated && rule.meta.type === 'layout'), -); - -const extensionRules = new Set( rules.filter( - rule => rule.meta.docs?.extendsBaseRule && !formattingRules.has(rule), + rule => !rule.meta.deprecated && rule.meta.fixable === 'whitespace', ), ); -const typescriptRules = rules.filter( +const emphasizedRules = rules.filter( rule => !rule.meta.deprecated && - !extensionRules.has(rule) && !deprecatedRules.has(rule) && !formattingRules.has(rule), ); @@ -68,17 +63,14 @@ module.exports = { someSidebar: [ 'README', { - ...createCategory('TypeScript Rules', Array.from(typescriptRules)), - collapsed: false, - }, - { - ...createCategory('Extension Rules', Array.from(extensionRules)), + ...createCategory('Rules', emphasizedRules, [ + createCategory('Formatting Rules', Array.from(formattingRules)), + createCategory('Deprecated Rules', [ + ...Array.from(deprecatedRules), + ...paths, + ]), + ]), collapsed: false, }, - createCategory('Formatting Rules', Array.from(formattingRules)), - createCategory('Deprecated Rules', [ - ...Array.from(deprecatedRules), - ...paths, - ]), ], }; From 4bbe09242b48b89afb5cbd80fa5c5102f6c6259d Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sun, 2 Oct 2022 04:39:17 -0400 Subject: [PATCH 12/14] Update packages/eslint-plugin/docs/rules/await-thenable.md Co-authored-by: Zzzen --- packages/eslint-plugin/docs/rules/await-thenable.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/docs/rules/await-thenable.md b/packages/eslint-plugin/docs/rules/await-thenable.md index 717f7e222008..8179a90af193 100644 --- a/packages/eslint-plugin/docs/rules/await-thenable.md +++ b/packages/eslint-plugin/docs/rules/await-thenable.md @@ -10,7 +10,7 @@ A "Thenable" value is an object with has a `then` method, such as a Promise. The `await` keyword is generally used to retrieve the result of calling a Thenable's `then` method. If the `await` keyword is used on a value that is not a Thenable, the value is directly resolved immediately. -While doing so is valid JavaScript, it i often a programmer error, such as forgetting to add parenthesis to call a function that returns a Promise. +While doing so is valid JavaScript, it is often a programmer error, such as forgetting to add parenthesis to call a function that returns a Promise. ## Examples From 9b85621b66078c3816c4014233209433d88d0b0f Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Tue, 4 Oct 2022 08:38:15 -0400 Subject: [PATCH 13/14] Blurgh, comment --- packages/eslint-plugin/docs/rules/no-non-null-assertion.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/docs/rules/no-non-null-assertion.md b/packages/eslint-plugin/docs/rules/no-non-null-assertion.md index 7e468da58985..6d4bed6f2a42 100644 --- a/packages/eslint-plugin/docs/rules/no-non-null-assertion.md +++ b/packages/eslint-plugin/docs/rules/no-non-null-assertion.md @@ -12,7 +12,7 @@ It's generally better to structure program logic so that TypeScript understands ## Examples - +Using non-null assertions cancels the benefits of the strict null-checking mode. From d8b22014b5f102633c0995ae85de75c4d0e4737d Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Tue, 4 Oct 2022 09:00:05 -0400 Subject: [PATCH 14/14] Update packages/eslint-plugin/docs/rules/no-non-null-assertion.md --- packages/eslint-plugin/docs/rules/no-non-null-assertion.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-non-null-assertion.md b/packages/eslint-plugin/docs/rules/no-non-null-assertion.md index 6d4bed6f2a42..d8ac3bd31048 100644 --- a/packages/eslint-plugin/docs/rules/no-non-null-assertion.md +++ b/packages/eslint-plugin/docs/rules/no-non-null-assertion.md @@ -12,8 +12,6 @@ It's generally better to structure program logic so that TypeScript understands ## Examples -Using non-null assertions cancels the benefits of the strict null-checking mode. - ### ❌ Incorrect