Первый коммит

This commit is contained in:
Аришина)
2024-08-20 23:25:37 +04:00
parent 146c332490
commit 49fc899684
60810 changed files with 5617373 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
---
title: Overview
sidebar_label: Overview
pagination_next: null
pagination_prev: null
slug: /
---
`@typescript-eslint/eslint-plugin` includes over 100 rules that detect best practice violations, bugs, and/or stylistic issues specifically for TypeScript code.
See [Configs](/linting/configs) for how to enable recommended rules using configs.
## Supported Rules
import RulesTable from "@site/src/components/RulesTable";
<RulesTable ruleset="supported-rules" />
## 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.
<RulesTable ruleset="extension-rules" />

View File

@@ -0,0 +1,26 @@
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/your-rule-name** for documentation.
## Examples
To fill out: tell us more about this rule.
<!--tabs-->
### ❌ Incorrect
```ts
// To fill out: incorrect code
```
### ✅ Correct
```ts
// To fill out: correct code
```
## When Not To Use It
To fill out: why wouldn't you want to use this rule?
For example if this rule requires a feature released in a certain TS version.

View File

@@ -0,0 +1,93 @@
---
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.
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.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
declare namespace Foo {
export function foo(s: string): void;
export function foo(n: number): void;
export function bar(): void;
export function foo(sn: string | number): void;
}
type Foo = {
foo(s: string): void;
foo(n: number): void;
bar(): void;
foo(sn: string | number): void;
};
interface Foo {
foo(s: string): void;
foo(n: number): void;
bar(): void;
foo(sn: string | number): void;
}
class Foo {
foo(s: string): void;
foo(n: number): void;
bar(): void {}
foo(sn: string | number): void {}
}
export function foo(s: string): void;
export function foo(n: number): void;
export function bar(): void;
export function foo(sn: string | number): void;
```
### ✅ Correct
```ts
declare namespace Foo {
export function foo(s: string): void;
export function foo(n: number): void;
export function foo(sn: string | number): void;
export function bar(): void;
}
type Foo = {
foo(s: string): void;
foo(n: number): void;
foo(sn: string | number): void;
bar(): void;
};
interface Foo {
foo(s: string): void;
foo(n: number): void;
foo(sn: string | number): void;
bar(): void;
}
class Foo {
foo(s: string): void;
foo(n: number): void;
foo(sn: string | number): void {}
bar(): void {}
}
export function bar(): void;
export function foo(s: string): void;
export function foo(n: number): void;
export function foo(sn: string | number): void;
```
## When Not To Use It
If you don't care about the general structure of the code, then you will not need this rule.

View File

@@ -0,0 +1,103 @@
---
description: 'Require consistently using either `T[]` or `Array<T>` for arrays.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/array-type** for documentation.
TypeScript provides two equivalent ways to define an array type: `T[]` and `Array<T>`.
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.
## Options
The default config will enforce that all mutable and readonly arrays use the `'array'` syntax.
### `"array"`
Always use `T[]` or `readonly T[]` for all array types.
<!--tabs-->
#### ❌ Incorrect
```ts
const x: Array<string> = ['a', 'b'];
const y: ReadonlyArray<string> = ['a', 'b'];
```
#### ✅ Correct
```ts
const x: string[] = ['a', 'b'];
const y: readonly string[] = ['a', 'b'];
```
### `"generic"`
Always use `Array<T>` or `ReadonlyArray<T>` for all array types.
<!--tabs-->
#### ❌ Incorrect
```ts
const x: string[] = ['a', 'b'];
const y: readonly string[] = ['a', 'b'];
```
#### ✅ Correct
```ts
const x: Array<string> = ['a', 'b'];
const y: ReadonlyArray<string> = ['a', 'b'];
```
### `"array-simple"`
Use `T[]` or `readonly T[]` for simple types (i.e. types which are just primitive names or type references).
Use `Array<T>` or `ReadonlyArray<T>` for all other types (union types, intersection types, object types, function types, etc).
<!--tabs-->
#### ❌ Incorrect
```ts
const a: (string | number)[] = ['a', 'b'];
const b: { prop: string }[] = [{ prop: 'a' }];
const c: (() => void)[] = [() => {}];
const d: Array<MyType> = ['a', 'b'];
const e: Array<string> = ['a', 'b'];
const f: ReadonlyArray<string> = ['a', 'b'];
```
#### ✅ Correct
```ts
const a: Array<string | number> = ['a', 'b'];
const b: Array<{ prop: string }> = [{ prop: 'a' }];
const c: Array<() => void> = [() => {}];
const d: MyType[] = ['a', 'b'];
const e: string[] = ['a', 'b'];
const f: readonly string[] = ['a', 'b'];
```
## Combination Matrix
This matrix lists all possible option combinations and their expected results for different types of Arrays.
| defaultOption | readonlyOption | Array with simple type | Array with non simple type | Readonly array with simple type | Readonly array with non simple type |
| -------------- | -------------- | ---------------------- | -------------------------- | ------------------------------- | ----------------------------------- |
| `array` | | `number[]` | `(Foo & Bar)[]` | `readonly number[]` | `readonly (Foo & Bar)[]` |
| `array` | `array` | `number[]` | `(Foo & Bar)[]` | `readonly number[]` | `readonly (Foo & Bar)[]` |
| `array` | `array-simple` | `number[]` | `(Foo & Bar)[]` | `readonly number[]` | `ReadonlyArray<Foo & Bar>` |
| `array` | `generic` | `number[]` | `(Foo & Bar)[]` | `ReadonlyArray<number>` | `ReadonlyArray<Foo & Bar>` |
| `array-simple` | | `number[]` | `Array<Foo & Bar>` | `readonly number[]` | `ReadonlyArray<Foo & Bar>` |
| `array-simple` | `array` | `number[]` | `Array<Foo & Bar>` | `readonly number[]` | `readonly (Foo & Bar)[]` |
| `array-simple` | `array-simple` | `number[]` | `Array<Foo & Bar>` | `readonly number[]` | `ReadonlyArray<Foo & Bar>` |
| `array-simple` | `generic` | `number[]` | `Array<Foo & Bar>` | `ReadonlyArray<number>` | `ReadonlyArray<Foo & Bar>` |
| `generic` | | `Array<number>` | `Array<Foo & Bar>` | `ReadonlyArray<number>` | `ReadonlyArray<Foo & Bar>` |
| `generic` | `array` | `Array<number>` | `Array<Foo & Bar>` | `readonly number[]` | `readonly (Foo & Bar)[]` |
| `generic` | `array-simple` | `Array<number>` | `Array<Foo & Bar>` | `readonly number[]` | `ReadonlyArray<Foo & Bar>` |
| `generic` | `generic` | `Array<number>` | `Array<Foo & Bar>` | `ReadonlyArray<number>` | `ReadonlyArray<Foo & Bar>` |

View File

@@ -0,0 +1,40 @@
---
description: 'Disallow awaiting a value that is not a Thenable.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/await-thenable** for documentation.
A "Thenable" value is an object which 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 is often a programmer error, such as forgetting to add parenthesis to call a function that returns a Promise.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
await 'value';
const createValue = () => 'value';
await createValue();
```
### ✅ Correct
```ts
await Promise.resolve('value');
const createValue = async () => 'value';
await createValue();
```
## When Not To Use It
If you want to allow code to `await` non-Promise values.
This is generally not preferred, but can sometimes be useful for visual consistency.

View File

@@ -0,0 +1,148 @@
---
description: 'Disallow `@ts-<directive>` comments or require descriptions after directives.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> 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.
Instead, it's generally better to correct the types of code, to make directives unnecessary.
The directive comments supported by TypeScript are:
```ts
// @ts-expect-error
// @ts-ignore
// @ts-nocheck
// @ts-check
```
This rule lets you set which directive comments you want to allow in your codebase.
## Options
By default, only `@ts-check` is allowed, as it enables rather than suppresses errors.
### `ts-expect-error`, `ts-ignore`, `ts-nocheck`, `ts-check` directives
A value of `true` for a particular directive means that this rule will report if it finds any usage of said directive.
<!--tabs-->
#### ❌ Incorrect
```ts
if (false) {
// @ts-ignore: Unreachable code error
console.log('hello');
}
if (false) {
/*
@ts-ignore: Unreachable code error
*/
console.log('hello');
}
```
#### ✅ Correct
```ts
if (false) {
// Compiler warns about unreachable code error
console.log('hello');
}
```
### `allow-with-description`
A value of `'allow-with-description'` for a particular directive means that this rule will report if it finds a directive that does not have a description following the directive (on the same line).
For example, with `{ 'ts-expect-error': 'allow-with-description' }`:
<!--tabs-->
#### ❌ Incorrect
```ts
if (false) {
// @ts-expect-error
console.log('hello');
}
if (false) {
/* @ts-expect-error */
console.log('hello');
}
```
#### ✅ Correct
```ts
if (false) {
// @ts-expect-error: Unreachable code error
console.log('hello');
}
if (false) {
/*
@ts-expect-error: Unreachable code error
*/
console.log('hello');
}
```
### `descriptionFormat`
For each directive type, you can specify a custom format in the form of a regular expression. Only description that matches the pattern will be allowed.
For example, with `{ 'ts-expect-error': { descriptionFormat: '^: TS\\d+ because .+$' } }`:
<!--tabs-->
#### ❌ Incorrect
```ts
// @ts-expect-error: the library definition is wrong
const a = doSomething('hello');
```
#### ✅ Correct
```ts
// @ts-expect-error: TS1234 because the library definition is wrong
const a = doSomething('hello');
```
### `minimumDescriptionLength`
Use `minimumDescriptionLength` to set a minimum length for descriptions when using the `allow-with-description` option for a directive.
For example, with `{ 'ts-expect-error': 'allow-with-description', minimumDescriptionLength: 10 }` the following pattern is:
<!--tabs-->
#### ❌ Incorrect
```ts
if (false) {
// @ts-expect-error: TODO
console.log('hello');
}
```
#### ✅ Correct
```ts
if (false) {
// @ts-expect-error The rationale for this override is described in issue #1337 on GitLab
console.log('hello');
}
```
## When Not To Use It
If you want to use all of the TypeScript directives.
## Further Reading
- TypeScript [Type Checking JavaScript Files](https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html)

View File

@@ -0,0 +1,39 @@
---
description: 'Disallow `// tslint:<rule-flag>` comments.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/ban-tslint-comment** for documentation.
Useful when migrating from TSLint to ESLint. Once TSLint has been removed, this rule helps locate TSLint annotations (e.g. `// tslint:disable`).
> See the [TSLint rule flags docs](https://palantir.github.io/tslint/usage/rule-flags) for reference.
## Examples
<!--tabs-->
### ❌ Incorrect
```js
/* tslint:disable */
/* tslint:enable */
/* tslint:disable:rule1 rule2 rule3... */
/* tslint:enable:rule1 rule2 rule3... */
// tslint:disable-next-line
someCode(); // tslint:disable-line
// tslint:disable-next-line:rule1 rule2 rule3...
```
### ✅ Correct
```js
// This is a comment that just happens to mention tslint
/* This is a multiline comment that just happens to mention tslint */
someCode(); // This is a comment that just happens to mention tslint
```
## When Not To Use It
If you are still using TSLint.

View File

@@ -0,0 +1,183 @@
---
description: 'Disallow certain types.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/ban-types** for documentation.
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.
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:
<!--tabs-->
### ❌ Incorrect
```ts
// use lower-case primitives for consistency
const str: String = 'foo';
const bool: Boolean = true;
const num: Number = 1;
const symb: Symbol = Symbol('foo');
const bigInt: BigInt = 1n;
// use a proper function type
const func: Function = () => 1;
// use safer object types
const lowerObj: Object = {};
const capitalObj: Object = { a: 'string' };
const curly1: {} = 1;
const curly2: {} = { a: 'string' };
```
### ✅ Correct
```ts
// use lower-case primitives for consistency
const str: string = 'foo';
const bool: boolean = true;
const num: number = 1;
const symb: symbol = Symbol('foo');
const bigInt: bigint = 1n;
// use a proper function type
const func: () => number = () => 1;
// use safer object types
const lowerObj: object = {};
const capitalObj: { a: string } = { a: 'string' };
const curly1: number = 1;
const curly2: Record<'a', string> = { a: 'string' };
```
## Options
The default options provide a set of "best practices", intended to provide safety and standardization in your codebase:
- Don't use the upper-case primitive types, you should use the lower-case types for consistency.
- Avoid the `Function` type, as it provides little safety for the following reasons:
- It provides no type safety when calling the value, which means it's easy to provide the wrong arguments.
- It accepts class declarations, which will fail when called, as they are called without the `new` keyword.
- Avoid the `Object` and `{}` types, as they mean "any non-nullish value".
- This is a point of confusion for many developers, who think it means "any object type".
- See [this comment for more information](https://github.com/typescript-eslint/typescript-eslint/issues/2063#issuecomment-675156492).
<details>
<summary>Default Options</summary>
```ts
const defaultTypes = {
String: {
message: 'Use string instead',
fixWith: 'string',
},
Boolean: {
message: 'Use boolean instead',
fixWith: 'boolean',
},
Number: {
message: 'Use number instead',
fixWith: 'number',
},
Symbol: {
message: 'Use symbol instead',
fixWith: 'symbol',
},
BigInt: {
message: 'Use bigint instead',
fixWith: 'bigint',
},
Function: {
message: [
'The `Function` type accepts any function-like value.',
'It provides no type safety when calling the function, which can be a common source of bugs.',
'It also accepts things like class declarations, which will throw at runtime as they will not be called with `new`.',
'If you are expecting the function to accept certain arguments, you should explicitly define the function shape.',
].join('\n'),
},
// object typing
Object: {
message: [
'The `Object` type actually means "any non-nullish value", so it is marginally better than `unknown`.',
'- If you want a type meaning "any object", you probably want `object` instead.',
'- If you want a type meaning "any value", you probably want `unknown` instead.',
'- If you really want a type meaning "any non-nullish value", you probably want `NonNullable<unknown>` instead.',
].join('\n'),
suggest: ['object', 'unknown', 'NonNullable<unknown>'],
},
'{}': {
message: [
'`{}` actually means "any non-nullish value".',
'- If you want a type meaning "any object", you probably want `object` instead.',
'- If you want a type meaning "any value", you probably want `unknown` instead.',
'- If you want a type meaning "empty object", you probably want `Record<string, never>` instead.',
'- If you really want a type meaning "any non-nullish value", you probably want `NonNullable<unknown>` instead.',
].join('\n'),
suggest: [
'object',
'unknown',
'Record<string, never>',
'NonNullable<unknown>',
],
},
};
```
</details>
### `types`
An object whose keys are the types you want to ban, and the values are error messages.
The type can either be a type name literal (`Foo`), a type name with generic parameter instantiation(s) (`Foo<Bar>`), the empty object literal (`{}`), or the empty tuple type (`[]`).
The values can be:
- A string, which is the error message to be reported; or
- `false` to specifically un-ban this type (useful when you are using `extendDefaults`); or
- An object with the following properties:
- `message: string` - the message to display when the type is matched.
- `fixWith?: string` - a string to replace the banned type with when the fixer is run. If this is omitted, no fix will be done.
- `suggest?: string[]` - a list of suggested replacements for the banned type.
### `extendDefaults`
If you're specifying custom `types`, you can set this to `true` to extend the default `types` configuration. This is a convenience option to save you copying across the defaults when adding another type.
If this is `false`, the rule will _only_ use the types defined in your configuration.
Example configuration:
```jsonc
{
"@typescript-eslint/ban-types": [
"error",
{
"types": {
// add a custom message to help explain why not to use it
"Foo": "Don't use Foo because it is unsafe",
// add a custom message, AND tell the plugin how to fix it
"OldAPI": {
"message": "Use NewAPI instead",
"fixWith": "NewAPI"
},
// un-ban a type that's banned by default
"{}": false
},
"extendDefaults": true
}
]
}
```

View File

@@ -0,0 +1,12 @@
---
description: 'Disallow or enforce spaces inside of blocks after opening block and before closing block.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/block-spacing** for documentation.
## Examples
This rule extends the base [`eslint/block-spacing`](https://eslint.org/docs/rules/block-spacing) rule.
This version adds support for TypeScript related blocks (interfaces, object type literals and enums).

View File

@@ -0,0 +1,12 @@
---
description: 'Enforce consistent brace style for blocks.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/brace-style** for documentation.
## 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.

View File

@@ -0,0 +1,10 @@
:::danger Deprecated
This rule has been deprecated in favour of the [`naming-convention`](./naming-convention.md) rule.
:::
<!--
This doc file has been left on purpose because `camelcase` is a core eslint rule.
This exists to help direct people to the replacement rule.
-->

View File

@@ -0,0 +1,114 @@
---
description: 'Enforce that literals on classes are exposed in a consistent style.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/class-literal-property-style** for documentation.
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.
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.
This is because these types can be mutated and carry with them more complex implications about their usage.
:::
### `"fields"`
This style checks for any getter methods that return literal values, and requires them to be defined using fields with the `readonly` modifier instead.
Examples of code with the `fields` style:
<!--tabs-->
#### ❌ Incorrect
```ts
/* eslint @typescript-eslint/class-literal-property-style: ["error", "fields"] */
class Mx {
public static get myField1() {
return 1;
}
private get ['myField2']() {
return 'hello world';
}
}
```
#### ✅ Correct
```ts
/* eslint @typescript-eslint/class-literal-property-style: ["error", "fields"] */
class Mx {
public readonly myField1 = 1;
// not a literal
public readonly myField2 = [1, 2, 3];
private readonly ['myField3'] = 'hello world';
public get myField4() {
return `hello from ${window.location.href}`;
}
}
```
### `"getters"`
This style checks for any `readonly` fields that are assigned literal values, and requires them to be defined as getters instead.
This style pairs well with the [`@typescript-eslint/prefer-readonly`](prefer-readonly.md) rule,
as it will identify fields that can be `readonly`, and thus should be made into getters.
Examples of code with the `getters` style:
<!--tabs-->
#### ❌ Incorrect
```ts
/* eslint @typescript-eslint/class-literal-property-style: ["error", "getters"] */
class Mx {
readonly myField1 = 1;
readonly myField2 = `hello world`;
private readonly myField3 = 'hello world';
}
```
#### ✅ Correct
```ts
/* eslint @typescript-eslint/class-literal-property-style: ["error", "getters"] */
class Mx {
// no readonly modifier
public myField1 = 'hello';
// not a literal
public readonly myField2 = [1, 2, 3];
public static get myField3() {
return 1;
}
private get ['myField4']() {
return 'hello world';
}
}
```
## When Not To Use It
When you have no strong preference, or do not wish to enforce a particular style
for how literal values are exposed by your classes.

View File

@@ -0,0 +1,22 @@
---
description: 'Require or disallow trailing commas.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/comma-dangle** for documentation.
## Examples
This rule extends the base [`eslint/comma-dangle`](https://eslint.org/docs/rules/comma-dangle) rule.
It adds support for TypeScript syntax.
See the [ESLint documentation](https://eslint.org/docs/rules/comma-dangle) for more details on the `comma-dangle` rule.
## How to Use
In addition to the options supported by the `comma-dangle` rule in ESLint core, the rule adds the following options:
- `"enums"` is for trailing comma in enum. (e.g. `enum Foo = {Bar,}`)
- `"generics"` is for trailing comma in generic. (e.g. `function foo<T,>() {}`)
- `"tuples"` is for trailing comma in tuple. (e.g. `type Foo = [string,]`)

View File

@@ -0,0 +1,12 @@
---
description: 'Enforce consistent spacing before and after commas.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/comma-spacing** for documentation.
## 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.

View File

@@ -0,0 +1,73 @@
---
description: 'Enforce specifying generic type arguments on type annotation or constructor name of a constructor call.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/consistent-generic-constructors** for documentation.
When constructing a generic class, you can specify the type arguments on either the left-hand side (as a type annotation) or the right-hand side (as part of the constructor call):
```ts
// Left-hand side
const map: Map<string, number> = new Map();
// Right-hand side
const map = new Map<string, number>();
```
This rule ensures that type arguments appear consistently on one side of the declaration.
Keeping to one side consistently improve code readability.
> 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
- `constructor` _(default)_: type arguments that **only** appear on the type annotation are disallowed.
- `type-annotation`: type arguments that **only** appear on the constructor are disallowed.
### `constructor`
<!--tabs-->
#### ❌ Incorrect
```ts
const map: Map<string, number> = new Map();
const set: Set<string> = new Set();
```
#### ✅ Correct
```ts
const map = new Map<string, number>();
const map: Map<string, number> = new MyMap();
const set = new Set<string>();
const set = new Set();
const set: Set<string> = new Set<string>();
```
### `type-annotation`
<!--tabs-->
#### ❌ Incorrect
```ts
const map = new Map<string, number>();
const set = new Set<string>();
```
#### ✅ Correct
```ts
const map: Map<string, number> = new Map();
const set: Set<string> = new Set();
const set = new Set();
const set: Set<string> = new Set<string>();
```
## When Not To Use It
You can turn this rule off if you don't want to enforce one kind of generic constructor style over the other.

View File

@@ -0,0 +1,80 @@
---
description: 'Require or disallow the `Record` type.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/consistent-indexed-object-style** for documentation.
TypeScript supports defining arbitrary object keys using an index signature. TypeScript also has a builtin type named `Record` to create an empty object defining only an index signature. For example, the following types are equal:
```ts
interface Foo {
[key: string]: unknown;
}
type Foo = {
[key: string]: unknown;
};
type Foo = Record<string, unknown>;
```
Keeping to one declaration form consistently improve code readability.
## Options
- `"record"` _(default)_: only allow the `Record` type.
- `"index-signature"`: only allow index signatures.
### `record`
<!--tabs-->
#### ❌ Incorrect
```ts
/* eslint @typescript-eslint/consistent-indexed-object-style: ["error", "record"] */
interface Foo {
[key: string]: unknown;
}
type Foo = {
[key: string]: unknown;
};
```
#### ✅ Correct
```ts
/* eslint @typescript-eslint/consistent-indexed-object-style: ["error", "record"] */
type Foo = Record<string, unknown>;
```
### `index-signature`
<!--tabs-->
#### ❌ Incorrect
```ts
/* eslint @typescript-eslint/consistent-indexed-object-style: ["error", "index-signature"] */
type Foo = Record<string, unknown>;
```
#### ✅ Correct
```ts
/* eslint @typescript-eslint/consistent-indexed-object-style: ["error", "index-signature"] */
interface Foo {
[key: string]: unknown;
}
type Foo = {
[key: string]: unknown;
};
```

View File

@@ -0,0 +1,108 @@
---
description: 'Enforce consistent usage of type assertions.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/consistent-type-assertions** for documentation.
TypeScript provides two syntaxes for "type assertions":
- Angle brackets: `<Type>value`
- As: `value as Type`
This rule aims to standardize the use of type assertion style across the codebase.
Keeping to one syntax consistently helps with code readability.
:::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 = <const>"hello";`.
## Options
### `assertionStyle`
This option defines the expected assertion style. Valid values for `assertionStyle` are:
- `as` will enforce that you always use `... as foo`.
- `angle-bracket` will enforce that you always use `<foo>...`
- `never` will enforce that you do not do any type assertions.
Most codebases will want to enforce not using `angle-bracket` style because it conflicts with JSX syntax, and is confusing when paired with generic syntax.
Some codebases like to go for an extra level of type safety, and ban assertions altogether via the `never` option.
### `objectLiteralTypeAssertions`
Always prefer `const x: T = { ... };` to `const x = { ... } as T;` (or similar with angle brackets). The type assertion in the latter case is either unnecessary or will probably hide an error.
The compiler will warn for excess properties with this syntax, but not missing _required_ fields. For example: `const x: { foo: number } = {};` will fail to compile, but `const x = {} as { foo: number }` will succeed.
The const assertion `const x = { foo: 1 } as const`, introduced in TypeScript 3.4, is considered beneficial and is ignored by this option.
Assertions to `any` are also ignored by this option.
Examples of code for `{ assertionStyle: 'as', objectLiteralTypeAssertions: 'never' }`:
<!--tabs-->
#### ❌ Incorrect
```ts
const x = { ... } as T;
function foo() {
return { ... } as T;
}
```
#### ✅ Correct
```ts
const x: T = { ... };
const y = { ... } as any;
const z = { ... } as unknown;
function foo(): T {
return { ... };
}
```
<!--/tabs-->
Examples of code for `{ assertionStyle: 'as', objectLiteralTypeAssertions: 'allow-as-parameter' }`:
<!--tabs-->
#### ❌ Incorrect
```ts
const x = { ... } as T;
function foo() {
return { ... } as T;
}
```
#### ✅ Correct
```tsx
const x: T = { ... };
const y = { ... } as any;
const z = { ... } as unknown;
foo({ ... } as T);
new Clazz({ ... } as T);
function foo() { throw { bar: 5 } as Foo }
const foo = <Foo props={{ ... } as Bar}/>;
```
<!--/tabs-->
## When Not To Use It
If you do not want to enforce consistent type assertions.

View File

@@ -0,0 +1,82 @@
---
description: 'Enforce type definitions to consistently use either `interface` or `type`.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/consistent-type-definitions** for documentation.
TypeScript provides two common ways to define an object type: `interface` and `type`.
```ts
// type alias
type T1 = {
a: string;
b: number;
};
// interface keyword
interface T2 {
a: string;
b: number;
}
```
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.
- `"type"`: enforce using `type`s for object type definitions.
### `interface`
<!--tabs-->
#### ❌ Incorrect
```ts
/* eslint @typescript-eslint/consistent-type-definitions: ["error", "interface"] */
type T = { x: number };
```
#### ✅ Correct
```ts
/* eslint @typescript-eslint/consistent-type-definitions: ["error", "interface"] */
type T = string;
type Foo = string | {};
interface T {
x: number;
}
```
### `type`
<!--tabs-->
#### ❌ Incorrect
```ts
/* eslint @typescript-eslint/consistent-type-definitions: ["error", "type"] */
interface T {
x: number;
}
```
#### ✅ Correct
```ts
/* eslint @typescript-eslint/consistent-type-definitions: ["error", "type"] */
type T = { x: number };
```
## When Not To Use It
If you specifically want to use an interface or type literal for stylistic reasons, you can disable this rule.

View File

@@ -0,0 +1,100 @@
---
description: 'Enforce consistent usage of type exports.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/consistent-type-exports** for documentation.
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.
> See [Blog > Consistent Type Exports and Imports: Why and How](/blog/consistent-type-imports-and-exports-why-and-how) for more details.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
interface ButtonProps {
onClick: () => void;
}
class Button implements ButtonProps {
onClick = () => console.log('button!');
}
export { Button, ButtonProps };
```
### ✅ Correct
```ts
interface ButtonProps {
onClick: () => void;
}
class Button implements ButtonProps {
onClick = () => console.log('button!');
}
export { Button };
export type { ButtonProps };
```
## Options
### `fixMixedExportsWithInlineTypeSpecifier`
When this is set to true, the rule will autofix "mixed" export cases using TS 4.5's "inline type specifier".
If you are using a TypeScript version less than 4.5, then you will not be able to use this option.
For example the following code:
```ts
const x = 1;
type T = number;
export { x, T };
```
With `{fixMixedExportsWithInlineTypeSpecifier: true}` will be fixed to:
```ts
const x = 1;
type T = number;
export { x, type T };
```
With `{fixMixedExportsWithInlineTypeSpecifier: false}` will be fixed to:
```ts
const x = 1;
type T = number;
export type { T };
export { x };
```
<!--tabs-->
### ❌ Incorrect
```ts
export { Button } from 'some-library';
export type { ButtonProps } from 'some-library';
```
### ✅ Correct
```ts
export { Button, type ButtonProps } from 'some-library';
```
## When Not To Use It
- If you specifically want to use both export kinds for stylistic reasons, you can disable this rule.
- If you use `--isolatedModules` the compiler would error if a type is not re-exported using `export type`. If you also don't wish to enforce one style over the other, you can disable this rule.

View File

@@ -0,0 +1,105 @@
---
description: 'Enforce consistent usage of type imports.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/consistent-type-imports** for documentation.
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.
> See [Blog > Consistent Type Exports and Imports: Why and How](/blog/consistent-type-imports-and-exports-why-and-how) for more details.
## Options
### `prefer`
This option defines the expected import kind for type-only imports. Valid values for `prefer` are:
- `type-imports` will enforce that you always use `import type Foo from '...'` except referenced by metadata of decorators. It is the default.
- `no-type-imports` will enforce that you always use `import Foo from '...'`.
Examples of **correct** code with `{prefer: 'type-imports'}`, and **incorrect** code with `{prefer: 'no-type-imports'}`.
```ts
import type { Foo } from 'Foo';
import type Bar from 'Bar';
type T = Foo;
const x: Bar = 1;
```
Examples of **incorrect** code with `{prefer: 'type-imports'}`, and **correct** code with `{prefer: 'no-type-imports'}`.
```ts
import { Foo } from 'Foo';
import Bar from 'Bar';
type T = Foo;
const x: Bar = 1;
```
### `fixStyle`
This option defines the expected type modifier to be added when an import is detected as used only in the type position. Valid values for `fixStyle` are:
- `separate-type-imports` will add the type keyword after the import keyword `import type { A } from '...'`. It is the default.
- `inline-type-imports` will inline the type keyword `import { type A } from '...'` and is only available in TypeScript 4.5 and onwards. See [documentation here](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html#type-modifiers-on-import-names 'TypeScript 4.5 documentation on type modifiers and import names').
<!--tabs-->
#### ❌ Incorrect
```ts
import { Foo } from 'Foo';
import Bar from 'Bar';
type T = Foo;
const x: Bar = 1;
```
#### ✅ With `separate-type-imports`
```ts
import type { Foo } from 'Foo';
import type Bar from 'Bar';
type T = Foo;
const x: Bar = 1;
```
#### ✅ With `inline-type-imports`
```ts
import { type Foo } from 'Foo';
import type Bar from 'Bar';
type T = Foo;
const x: Bar = 1;
```
<!--tabs-->
### `disallowTypeAnnotations`
If `true`, type imports in type annotations (`import()`) are not allowed.
Default is `true`.
Examples of **incorrect** code with `{disallowTypeAnnotations: true}`:
```ts
type T = import('Foo').Foo;
const x: import('Bar') = 1;
```
## Usage with `emitDecoratorMetadata`
The `emitDecoratorMetadata` compiler option changes the code the TypeScript emits. In short - it causes TypeScript to create references to value imports when they are used in a type-only location. If you are using `emitDecoratorMetadata` then our tooling will require additional information in order for the rule to work correctly.
If you are using [type-aware linting](https://typescript-eslint.io/linting/typed-linting), then you just need to ensure that the `tsconfig.json` you've configured for `parserOptions.project` has `emitDecoratorMetadata` turned on. Otherwise you can explicitly tell our tooling to analyze your code as if the compiler option was turned on [by setting `parserOptions.emitDecoratorMetadata` to `true`](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/README.md#parseroptionsemitdecoratormetadata).
## When Not To Use It
- If you specifically want to use both import kinds for stylistic reasons, you can disable this rule.
## Related To
- [`no-import-type-side-effects`](./no-import-type-side-effects.md)
- [`import/consistent-type-specifier-style`](https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/consistent-type-specifier-style.md)
- [`import/no-duplicates` with `{"prefer-inline": true}`](https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-duplicates.md#inline-type-imports)

View File

@@ -0,0 +1,48 @@
---
description: 'Enforce default parameters to be last.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/default-param-last** for documentation.
## 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.
<!--tabs-->
### ❌ Incorrect
```ts
/* eslint @typescript-eslint/default-param-last: "error" */
function f(a = 0, b: number) {}
function f(a: number, b = 0, c: number) {}
function f(a: number, b?: number, c: number) {}
class Foo {
constructor(public a = 10, private b: number) {}
}
class Foo {
constructor(public a?: number, private b: number) {}
}
```
### ✅ Correct
```ts
/* eslint @typescript-eslint/default-param-last: "error" */
function f(a = 0) {}
function f(a: number, b = 0) {}
function f(a: number, b?: number) {}
function f(a: number, b?: number, c = 0) {}
function f(a: number, b = 0, c?: number) {}
class Foo {
constructor(public a, private b = 0) {}
}
class Foo {
constructor(public a, private b?: number) {}
}
```

View File

@@ -0,0 +1,77 @@
---
description: 'Enforce dot notation whenever possible.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/dot-notation** for documentation.
## Examples
This rule extends the base [`eslint/dot-notation`](https://eslint.org/docs/rules/dot-notation) rule.
It adds:
- Support for optionally ignoring computed `private` and/or `protected` member access.
- Compatibility with TypeScript's `noPropertyAccessFromIndexSignature` option.
## Options
This rule adds the following options:
```ts
interface Options extends BaseDotNotationOptions {
allowPrivateClassPropertyAccess?: boolean;
allowProtectedClassPropertyAccess?: boolean;
allowIndexSignaturePropertyAccess?: boolean;
}
const defaultOptions: Options = {
...baseDotNotationDefaultOptions,
allowPrivateClassPropertyAccess: false,
allowProtectedClassPropertyAccess: false,
allowIndexSignaturePropertyAccess: false,
};
```
If the TypeScript compiler option `noPropertyAccessFromIndexSignature` is set to `true`, then this rule always allows the use of square bracket notation to access properties of types that have a `string` index signature, even if `allowIndexSignaturePropertyAccess` is `false`.
### `allowPrivateClassPropertyAccess`
Example of a correct code when `allowPrivateClassPropertyAccess` is set to `true`:
```ts
class X {
private priv_prop = 123;
}
const x = new X();
x['priv_prop'] = 123;
```
### `allowProtectedClassPropertyAccess`
Example of a correct code when `allowProtectedClassPropertyAccess` is set to `true`:
```ts
class X {
protected protected_prop = 123;
}
const x = new X();
x['protected_prop'] = 123;
```
### `allowIndexSignaturePropertyAccess`
Example of correct code when `allowIndexSignaturePropertyAccess` is set to `true`:
```ts
class X {
[key: string]: number;
}
const x = new X();
x['hello'] = 123;
```
If the TypeScript compiler option `noPropertyAccessFromIndexSignature` is set to `true`, then the above code is always allowed, even if `allowIndexSignaturePropertyAccess` is `false`.

View File

@@ -0,0 +1,319 @@
---
description: 'Require explicit return types on functions and class methods.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/explicit-function-return-type** for documentation.
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.
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.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
// Should indicate that no value is returned (void)
function test() {
return;
}
// Should indicate that a number is returned
var fn = function () {
return 1;
};
// Should indicate that a string is returned
var arrowFn = () => 'test';
class Test {
// Should indicate that no value is returned (void)
method() {
return;
}
}
```
### ✅ Correct
```ts
// No return value should be expected (void)
function test(): void {
return;
}
// A return value of type number
var fn = function (): number {
return 1;
};
// A return value of type string
var arrowFn = (): string => 'test';
class Test {
// No return value should be expected (void)
method(): void {
return;
}
}
```
## Options
### 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.
```jsonc
{
"rules": {
// disable the rule for all files
"@typescript-eslint/explicit-function-return-type": "off"
},
"overrides": [
{
// enable the rule specifically for TypeScript files
"files": ["*.ts", "*.mts", "*.cts", "*.tsx"],
"rules": {
"@typescript-eslint/explicit-function-return-type": "error"
}
}
]
}
```
### `allowExpressions`
Examples of code for this rule with `{ allowExpressions: true }`:
<!--tabs-->
#### ❌ Incorrect
```ts
function test() {}
const fn = () => {};
export default () => {};
```
#### ✅ Correct
```ts
node.addEventListener('click', () => {});
node.addEventListener('click', function () {});
const foo = arr.map(i => i * i);
```
### `allowTypedFunctionExpressions`
Examples of code for this rule with `{ allowTypedFunctionExpressions: true }`:
<!--tabs-->
#### ❌ Incorrect
```ts
let arrowFn = () => 'test';
let funcExpr = function () {
return 'test';
};
let objectProp = {
foo: () => 1,
};
```
#### ✅ Correct
```ts
type FuncType = () => string;
let arrowFn: FuncType = () => 'test';
let funcExpr: FuncType = function() {
return 'test';
};
let asTyped = (() => '') as () => string;
let castTyped = <() => string>(() => '');
interface ObjectType {
foo(): number;
}
let objectProp: ObjectType = {
foo: () => 1,
};
let objectPropAs = {
foo: () => 1,
} as ObjectType;
let objectPropCast = <ObjectType>{
foo: () => 1,
};
declare functionWithArg(arg: () => number);
functionWithArg(() => 1);
declare functionWithObjectArg(arg: { method: () => number });
functionWithObjectArg({
method() {
return 1;
},
});
```
### `allowHigherOrderFunctions`
Examples of code for this rule with `{ allowHigherOrderFunctions: true }`:
<!--tabs-->
#### ❌ Incorrect
```ts
var arrowFn = () => () => {};
function fn() {
return function () {};
}
```
#### ✅ Correct
```ts
var arrowFn = () => (): void => {};
function fn() {
return function (): void {};
}
```
### `allowDirectConstAssertionInArrowFunctions`
Examples of code for this rule with `{ allowDirectConstAssertionInArrowFunctions: true }`:
<!--tabs-->
#### ❌ Incorrect
```ts
const func = (value: number) => ({ type: 'X', value } as any);
const func = (value: number) => ({ type: 'X', value } as Action);
```
#### ✅ Correct
```ts
const func = (value: number) => ({ foo: 'bar', value } as const);
const func = () => x as const;
```
### `allowConciseArrowFunctionExpressionsStartingWithVoid`
Examples of code for this rule with `{ allowConciseArrowFunctionExpressionsStartingWithVoid: true }`:
<!--tabs-->
#### ❌ Incorrect
```ts
var join = (a: string, b: string) => `${a}${b}`;
const log = (message: string) => {
console.log(message);
};
```
#### ✅ Correct
```ts
var log = (message: string) => void console.log(message);
```
### `allowFunctionsWithoutTypeParameters`
Examples of code for this rule with `{ allowFunctionsWithoutTypeParameters: true }`:
<!--tabs-->
#### ❌ Incorrect
```ts
function foo<T>(t: T) {
return t;
}
const bar = <T>(t: T) => t;
```
#### ✅ Correct
```ts
function foo<T>(t: T): T {
return t;
}
const bar = <T>(t: T): T => t;
const allowedFunction(x: string) {
return x;
}
const allowedArrow = (x: string) => x;
```
### `allowedNames`
You may pass function/method names you would like this rule to ignore, like so:
```json
{
"@typescript-eslint/explicit-function-return-type": [
"error",
{
"allowedNames": ["ignoredFunctionName", "ignoredMethodName"]
}
]
}
```
### `allowIIFE`
Examples of code for this rule with `{ allowIIFE: true }`:
#### ❌ Incorrect
```ts
var func = () => 'foo';
```
#### ✅ Correct
```ts
var foo = (() => 'foo')();
var bar = (function () {
return 'bar';
})();
```
## When Not To Use It
If you don't wish to prevent calling code from using function return values in unexpected ways, then
you will not need this rule.
## Further Reading
- TypeScript [Functions](https://www.typescriptlang.org/docs/handbook/functions.html#function-types)

View File

@@ -0,0 +1,331 @@
---
description: 'Require explicit accessibility modifiers on class properties and methods.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/explicit-member-accessibility** for documentation.
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.
Some developers also find it preferable for code readability to keep member publicity explicit.
## Examples
This rule aims to make code more readable and explicit about who can use
which properties.
## Options
### 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.
```jsonc
{
"rules": {
// disable the rule for all files
"@typescript-eslint/explicit-member-accessibility": "off"
},
"overrides": [
{
// enable the rule specifically for TypeScript files
"files": ["*.ts", "*.mts", "*.cts", "*.tsx"],
"rules": {
"@typescript-eslint/explicit-member-accessibility": "error"
}
}
]
}
```
### `accessibility`
This rule in its default state requires no configuration and will enforce that every class member has an accessibility modifier. If you would like to allow for some implicit public members then you have the following options:
```ts
{
accessibility: 'explicit',
overrides: {
accessors: 'explicit',
constructors: 'no-public',
methods: 'explicit',
properties: 'off',
parameterProperties: 'explicit'
}
}
```
Note the above is an example of a possible configuration you could use - it is not the default configuration.
The following patterns are considered incorrect code if no options are provided:
```ts
class Animal {
constructor(name) {
// No accessibility modifier
this.animalName = name;
}
animalName: string; // No accessibility modifier
get name(): string {
// No accessibility modifier
return this.animalName;
}
set name(value: string) {
// No accessibility modifier
this.animalName = value;
}
walk() {
// method
}
}
```
The following patterns are considered correct with the default options `{ accessibility: 'explicit' }`:
```ts
class Animal {
public constructor(public breed, name) {
// Parameter property and constructor
this.animalName = name;
}
private animalName: string; // Property
get name(): string {
// get accessor
return this.animalName;
}
set name(value: string) {
// set accessor
this.animalName = value;
}
public walk() {
// method
}
}
```
The following patterns are considered incorrect with the accessibility set to **no-public** `[{ accessibility: 'no-public' }]`:
```ts
class Animal {
public constructor(public breed, name) {
// Parameter property and constructor
this.animalName = name;
}
public animalName: string; // Property
public get name(): string {
// get accessor
return this.animalName;
}
public set name(value: string) {
// set accessor
this.animalName = value;
}
public walk() {
// method
}
}
```
The following patterns are considered correct with the accessibility set to **no-public** `[{ accessibility: 'no-public' }]`:
```ts
class Animal {
constructor(protected breed, name) {
// Parameter property and constructor
this.name = name;
}
private animalName: string; // Property
get name(): string {
// get accessor
return this.animalName;
}
private set name(value: string) {
// set accessor
this.animalName = value;
}
protected walk() {
// method
}
}
```
### Overrides
There are three ways in which an override can be used.
- To disallow the use of public on a given member.
- To enforce explicit member accessibility when the root has allowed implicit public accessibility
- To disable any checks on given member type
#### Disallow the use of public on a given member
e.g. `[ { overrides: { constructors: 'no-public' } } ]`
The following patterns are considered incorrect with the example override
```ts
class Animal {
public constructor(protected animalName) {}
public get name() {
return this.animalName;
}
}
```
The following patterns are considered correct with the example override
```ts
class Animal {
constructor(protected animalName) {}
public get name() {
return this.animalName;
}
}
```
#### Require explicit accessibility for a given member
e.g. `[ { accessibility: 'no-public', overrides: { properties: 'explicit' } } ]`
The following patterns are considered incorrect with the example override
```ts
class Animal {
constructor(protected animalName) {}
get name() {
return this.animalName;
}
protected set name(value: string) {
this.animalName = value;
}
legs: number;
private hasFleas: boolean;
}
```
The following patterns are considered correct with the example override
```ts
class Animal {
constructor(protected animalName) {}
get name() {
return this.animalName;
}
protected set name(value: string) {
this.animalName = value;
}
public legs: number;
private hasFleas: boolean;
}
```
e.g. `[ { accessibility: 'off', overrides: { parameterProperties: 'explicit' } } ]`
The following code is considered incorrect with the example override
```ts
class Animal {
constructor(readonly animalName: string) {}
}
```
The following code patterns are considered correct with the example override
```ts
class Animal {
constructor(public readonly animalName: string) {}
}
class Animal {
constructor(public animalName: string) {}
}
class Animal {
constructor(animalName: string) {}
}
```
e.g. `[ { accessibility: 'off', overrides: { parameterProperties: 'no-public' } } ]`
The following code is considered incorrect with the example override
```ts
class Animal {
constructor(public readonly animalName: string) {}
}
```
The following code is considered correct with the example override
```ts
class Animal {
constructor(public animalName: string) {}
}
```
#### Disable any checks on given member type
e.g. `[{ overrides: { accessors : 'off' } } ]`
As no checks on the overridden member type are performed all permutations of visibility are permitted for that member type
The follow pattern is considered incorrect for the given configuration
```ts
class Animal {
constructor(protected animalName) {}
public get name() {
return this.animalName;
}
get legs() {
return this.legCount;
}
}
```
The following patterns are considered correct with the example override
```ts
class Animal {
public constructor(protected animalName) {}
public get name() {
return this.animalName;
}
get legs() {
return this.legCount;
}
}
```
### Except specific methods
If you want to ignore some specific methods, you can do it by specifying method names. Note that this option does not care for the context, and will ignore every method with these names, which could lead to it missing some cases. You should use this sparingly.
e.g. `[ { ignoredMethodNames: ['specificMethod', 'whateverMethod'] } ]`
```ts
class Animal {
get specificMethod() {
console.log('No error because you specified this method on option');
}
get whateverMethod() {
console.log('No error because you specified this method on option');
}
public get otherMethod() {
console.log('This method comply with this rule');
}
}
```
## When Not To Use It
If you think defaulting to public is a good default, then you should consider using the `no-public` setting. If you want to mix implicit and explicit public members then disable this rule.
## Further Reading
- TypeScript [Accessibility Modifiers Handbook Docs](https://www.typescriptlang.org/docs/handbook/2/classes.html#member-visibility)

View File

@@ -0,0 +1,250 @@
---
description: "Require explicit return and argument types on exported functions' and classes' public class methods."
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> 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.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
// Should indicate that no value is returned (void)
export function test() {
return;
}
// Should indicate that a number is returned
export default function () {
return 1;
}
// Should indicate that a string is returned
export var arrowFn = () => 'test';
// All arguments should be typed
export var arrowFn = (arg): string => `test ${arg}`;
export var arrowFn = (arg: any): string => `test ${arg}`;
export class Test {
// Should indicate that no value is returned (void)
method() {
return;
}
}
```
### ✅ Correct
```ts
// Function is not exported
function test() {
return;
}
// A return value of type number
export var fn = function (): number {
return 1;
};
// A return value of type string
export var arrowFn = (): string => 'test';
// All arguments should be typed
export var arrowFn = (arg: string): string => `test ${arg}`;
export var arrowFn = (arg: unknown): string => `test ${arg}`;
// Class is not exported
class Test {
method() {
return;
}
}
```
## Options
### 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.
```jsonc
{
"rules": {
// disable the rule for all files
"@typescript-eslint/explicit-module-boundary-types": "off"
},
"overrides": [
{
// enable the rule specifically for TypeScript files
"files": ["*.ts", "*.mts", "*.cts", "*.tsx"],
"rules": {
"@typescript-eslint/explicit-module-boundary-types": "error"
}
}
]
}
```
### `allowArgumentsExplicitlyTypedAsAny`
Examples of code for this rule with `{ allowArgumentsExplicitlyTypedAsAny: false }`:
<!--tabs-->
#### ❌ Incorrect
```ts
export const func = (value: any): number => value + 1;
```
#### ✅ Correct
```ts
export const func = (value: number): number => value + 1;
```
### `allowDirectConstAssertionInArrowFunctions`
Examples of code for this rule with `{ allowDirectConstAssertionInArrowFunctions: false }`:
<!--tabs-->
#### ❌ Incorrect
```ts
export const func = (value: number) => ({ type: 'X', value });
export const foo = () => ({
bar: true,
});
export const bar = () => 1;
```
#### ✅ Correct
```ts
export const func = (value: number) => ({ type: 'X', value } as const);
export const foo = () =>
({
bar: true,
} as const);
export const bar = () => 1 as const;
```
### `allowedNames`
You may pass function/method names you would like this rule to ignore, like so:
```json
{
"@typescript-eslint/explicit-module-boundary-types": [
"error",
{
"allowedNames": ["ignoredFunctionName", "ignoredMethodName"]
}
]
}
```
### `allowHigherOrderFunctions`
Examples of code for this rule with `{ allowHigherOrderFunctions: false }`:
<!--tabs-->
#### ❌ Incorrect
```ts
export const arrowFn = () => () => {};
export function fn() {
return function () {};
}
export function foo(outer: string) {
return function (inner: string) {};
}
```
#### ✅ Correct
```ts
export const arrowFn = () => (): void => {};
export function fn() {
return function (): void {};
}
export function foo(outer: string) {
return function (inner: string): void {};
}
```
### `allowTypedFunctionExpressions`
Examples of code for this rule with `{ allowTypedFunctionExpressions: false }`:
<!--tabs-->
#### ❌ Incorrect
```ts
export let arrowFn = () => 'test';
export let funcExpr = function () {
return 'test';
};
export let objectProp = {
foo: () => 1,
};
export const foo = bar => {};
```
#### ✅ Correct
```ts
type FuncType = () => string;
export let arrowFn: FuncType = () => 'test';
export let funcExpr: FuncType = function () {
return 'test';
};
export let asTyped = (() => '') as () => string;
export let castTyped = <() => string>(() => '');
interface ObjectType {
foo(): number;
}
export let objectProp: ObjectType = {
foo: () => 1,
};
export let objectPropAs = {
foo: () => 1,
} as ObjectType;
export let objectPropCast = <ObjectType>{
foo: () => 1,
};
type FooType = (bar: string) => void;
export const foo: FooType = bar => {};
```
## When Not To Use It
If you wish to make sure all functions have explicit return types, as opposed to only the module boundaries, you can use [explicit-function-return-type](./explicit-function-return-type.md)
## Further Reading
- TypeScript [Functions](https://www.typescriptlang.org/docs/handbook/functions.html#function-types)

View File

@@ -0,0 +1,12 @@
---
description: 'Require or disallow spacing between function identifiers and their invocations.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/func-call-spacing** for documentation.
## 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.

View File

@@ -0,0 +1,20 @@
---
description: 'Enforce consistent indentation.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/indent** for documentation.
## Warning
:::warning
Please read [Issue #1824: Problems with the indent rule](https://github.com/typescript-eslint/typescript-eslint/issues/1824) before using this rule!
:::
## Examples
This rule extends the base [`eslint/indent`](https://eslint.org/docs/rules/indent) rule.
It adds support for TypeScript nodes.

View File

@@ -0,0 +1,12 @@
---
description: 'Require or disallow initialization in variable declarations.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/init-declarations** for documentation.
## 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.

View File

@@ -0,0 +1,12 @@
---
description: 'Enforce consistent spacing between property names and type annotations in types and interfaces.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/key-spacing** for documentation.
## Examples
This rule extends the base [`eslint/key-spacing`](https://eslint.org/docs/rules/key-spacing) rule.
This version adds support for type annotations on interfaces, classes and type literals properties.

View File

@@ -0,0 +1,12 @@
---
description: 'Enforce consistent spacing before and after keywords.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/keyword-spacing** for documentation.
## 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.

View File

@@ -0,0 +1,37 @@
---
description: 'Require empty lines around comments.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/lines-around-comment** for documentation.
## Rule Details
This rule extends the base [`eslint/lines-around-comment`](https://eslint.org/docs/rules/lines-around-comment) rule.
It adds support for TypeScript syntax.
See the [ESLint documentation](https://eslint.org/docs/rules/lines-around-comment) for more details on the `comma-dangle` rule.
## Rule Changes
```jsonc
{
// note you must disable the base rule as it can report incorrect errors
"lines-around-comment": "off",
"@typescript-eslint/lines-around-comment": ["error"]
}
```
## Options
In addition to the options supported by the `lines-around-comment` rule in ESLint core, the rule adds the following options:
- `allowEnumEnd: true` doesn't require a blank line after an enum body block end
- `allowEnumStart: true` doesn't require a blank line before an enum body block start
- `allowInterfaceEnd: true` doesn't require a blank line before an interface body block end
- `allowInterfaceStart: true` doesn't require a blank line after an interface body block start
- `allowModuleEnd: true` doesn't require a blank line before a module body block end
- `allowModuleStart: true` doesn't require a blank line after a module body block start
- `allowTypeEnd: true` doesn't require a blank line before a type literal block end
- `allowTypeStart: true` doesn't require a blank line after a type literal block start

View File

@@ -0,0 +1,63 @@
---
description: 'Require or disallow an empty line between class members.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/lines-between-class-members** for documentation.
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.
## 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.
## Options
In addition to the options supported by the `lines-between-class-members` rule in ESLint core, the rule adds the following options:
- Object option:
- `"exceptAfterOverload": true` (default) - Skip checking empty lines after overload class members
- `"exceptAfterOverload": false` - **do not** skip checking empty lines after overload class members
- [See the other options allowed](https://github.com/eslint/eslint/blob/main/docs/rules/lines-between-class-members.md#options)
### `exceptAfterOverload: true`
Examples of **correct** code for the `{ "exceptAfterOverload": true }` option:
```ts
/*eslint @typescript-eslint/lines-between-class-members: ["error", "always", { "exceptAfterOverload": true }]*/
class foo {
bar(a: string): void;
bar(a: string, b: string): void;
bar(a: string, b: string) {}
baz() {}
qux() {}
}
```
### `exceptAfterOverload: false`
Examples of **correct** code for the `{ "exceptAfterOverload": false }` option:
```ts
/*eslint @typescript-eslint/lines-between-class-members: ["error", "always", { "exceptAfterOverload": false }]*/
class foo {
bar(a: string): void;
bar(a: string, b: string): void;
bar(a: string, b: string) {}
baz() {}
qux() {}
}
```

View File

@@ -0,0 +1,161 @@
---
description: 'Require a specific member delimiter style for interfaces and type literals.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/member-delimiter-style** for documentation.
TypeScript allows three delimiters between members in interfaces and type aliases:
<!-- prettier-ignore -->
```ts
interface Foo {
// Semicolons (default, preferred in TypeScript):
name: string;
// Commas (JSON-like):
name: string,
// Line breaks (none):
name: string
}
```
For code readability, it's generally best to use the same style consistently in your codebase.
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
Default config:
```json
{
"multiline": {
"delimiter": "semi",
"requireLast": true
},
"singleline": {
"delimiter": "semi",
"requireLast": false
},
"multilineDetection": "brackets"
}
```
`multiline` config only applies to multiline `interface`/`type` definitions.
`singleline` config only applies to single line `interface`/`type` definitions.
The two configs are entirely separate, and do not effect one another.
`multilineDetection` determines what counts as multiline
- `"brackets"` (default) any newlines in the type or interface make it multiline.
- `"last-member"` if the last member of the interface is on the same line as the last bracket, it is counted as a single line.
### `delimiter`
Accepts three values (or two for `singleline`):
- `comma` - each member should be delimited with a comma (`,`).
- `semi` - each member should be delimited with a semicolon (`;`).
- `none` - each member should be delimited with nothing.
:::note
`none` is not an option for `singleline` because having no delimiter between members on a single line is a syntax error in TS.
:::
### `requireLast`
Determines whether or not the last member in the `interface`/`type` should have a delimiter:
- `true` - the last member **_must_** have a delimiter.
- `false` - the last member **_must not_** have a delimiter.
### `overrides`
Allows you to specify options specifically for either `interface`s or `type` definitions / inline `type`s.
For example, to require commas for `type`s, and semicolons for multiline `interface`s:
```json
{
"multiline": {
"delimiter": "comma",
"requireLast": true
},
"singleline": {
"delimiter": "comma",
"requireLast": true
},
"overrides": {
"interface": {
"multiline": {
"delimiter": "semi",
"requireLast": true
}
}
}
}
```
## Examples
Examples of code for this rule with the default config:
<!--tabs-->
### ❌ Incorrect
<!-- prettier-ignore -->
```ts
// missing semicolon delimiter
interface Foo {
name: string
greet(): string
}
// using incorrect delimiter
interface Bar {
name: string,
greet(): string,
}
// missing last member delimiter
interface Baz {
name: string;
greet(): string
}
// incorrect delimiter
type FooBar = { name: string, greet(): string }
// last member should not have delimiter
type FooBar = { name: string; greet(): string; }
```
### ✅ Correct
<!-- prettier-ignore -->
```ts
interface Foo {
name: string;
greet(): string;
}
interface Foo { name: string }
type Bar = {
name: string;
greet(): string;
}
type Bar = { name: string }
type FooBar = { name: string; greet(): string }
```
## When Not To Use It
If you don't care about enforcing a consistent member delimiter in interfaces and type literals, then you will not need this rule.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,110 @@
---
description: 'Enforce using a particular method signature syntax.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/method-signature-style** for documentation.
TypeScript provides two ways to define an object/interface function property:
```ts
interface Example {
// method shorthand syntax
func(arg: string): number;
// 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:
> A method and a function property of the same type behave differently.
> Methods are always bivariant in their argument, while function properties are contravariant in their argument under `strictFunctionTypes`.
See the reasoning behind that in the [TypeScript PR for the compiler option](https://github.com/microsoft/TypeScript/pull/18654).
## Options
This rule accepts one string option:
- `"property"`: Enforce using property signature for functions. Use this to enforce maximum correctness together with TypeScript's strict mode.
- `"method"`: Enforce using method signature for functions. Use this if you aren't using TypeScript's strict mode and prefer this style.
The default is `"property"`.
### `property`
Examples of code with `property` option.
<!--tabs-->
#### ❌ Incorrect
```ts
interface T1 {
func(arg: string): number;
}
type T2 = {
func(arg: boolean): void;
};
interface T3 {
func(arg: number): void;
func(arg: string): void;
func(arg: boolean): void;
}
```
#### ✅ Correct
```ts
interface T1 {
func: (arg: string) => number;
}
type T2 = {
func: (arg: boolean) => void;
};
// this is equivalent to the overload
interface T3 {
func: ((arg: number) => void) &
((arg: string) => void) &
((arg: boolean) => void);
}
```
### `method`
Examples of code with `method` option.
<!--tabs-->
#### ❌ Incorrect
```ts
interface T1 {
func: (arg: string) => number;
}
type T2 = {
func: (arg: boolean) => void;
};
```
#### ✅ Correct
```ts
interface T1 {
func(arg: string): number;
}
type T2 = {
func(arg: boolean): void;
};
```
## When Not To Use It
If you don't want to enforce a particular style for object/interface function types, and/or if you don't use `strictFunctionTypes`, then you don't need this rule.

View File

@@ -0,0 +1,706 @@
---
description: 'Enforce naming conventions for everything across a codebase.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/naming-convention** for documentation.
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`.
## Examples
This rule allows you to enforce conventions for any identifier, using granular selectors to create a fine-grained style guide.
:::note
This rule only needs type information in specific cases, detailed below.
:::
## Options
This rule accepts an array of objects, with each object describing a different naming convention.
Each property will be described in detail below. Also see the examples section below for illustrated examples.
```ts
type Options = {
// format options
format:
| (
| 'camelCase'
| 'strictCamelCase'
| 'PascalCase'
| 'StrictPascalCase'
| 'snake_case'
| 'UPPER_CASE'
)[]
| null;
custom?: {
regex: string;
match: boolean;
};
leadingUnderscore?:
| 'forbid'
| 'require'
| 'requireDouble'
| 'allow'
| 'allowDouble'
| 'allowSingleOrDouble';
trailingUnderscore?:
| 'forbid'
| 'require'
| 'requireDouble'
| 'allow'
| 'allowDouble'
| 'allowSingleOrDouble';
prefix?: string[];
suffix?: string[];
// selector options
selector: Selector | Selector[];
filter?:
| string
| {
regex: string;
match: boolean;
};
// the allowed values for these are dependent on the selector - see below
modifiers?: Modifiers<Selector>[];
types?: Types<Selector>[];
}[];
// the default config is similar to ESLint's camelcase rule but more strict
const defaultOptions: Options = [
{
selector: 'default',
format: ['camelCase'],
leadingUnderscore: 'allow',
trailingUnderscore: 'allow',
},
{
selector: 'variable',
format: ['camelCase', 'UPPER_CASE'],
leadingUnderscore: 'allow',
trailingUnderscore: 'allow',
},
{
selector: 'typeLike',
format: ['PascalCase'],
},
];
```
### Format Options
Every single selector can have the same set of format options.
For information about how each selector is applied, see ["How does the rule evaluate a name's format?"](#how-does-the-rule-evaluate-a-names-format).
#### `format`
The `format` option defines the allowed formats for the identifier. This option accepts an array of the following values, and the identifier can match any of them:
- `camelCase` - standard camelCase format - no underscores are allowed between characters, and consecutive capitals are allowed (i.e. both `myID` and `myId` are valid).
- `PascalCase` - same as `camelCase`, except the first character must be upper-case.
- `snake_case` - standard snake_case format - all characters must be lower-case, and underscores are allowed.
- `strictCamelCase` - same as `camelCase`, but consecutive capitals are not allowed (i.e. `myId` is valid, but `myID` is not).
- `StrictPascalCase` - same as `strictCamelCase`, except the first character must be upper-case.
- `UPPER_CASE` - same as `snake_case`, except all characters must be upper-case.
Instead of an array, you may also pass `null`. This signifies "this selector shall not have its format checked".
This can be useful if you want to enforce no particular format for a specific selector, after applying a group selector.
#### `custom`
The `custom` option defines a custom regex that the identifier must (or must not) match. This option allows you to have a bit more finer-grained control over identifiers, letting you ban (or force) certain patterns and substrings.
Accepts an object with the following properties:
- `match` - true if the identifier _must_ match the `regex`, false if the identifier _must not_ match the `regex`.
- `regex` - a string that is then passed into RegExp to create a new regular expression: `new RegExp(regex)`
#### `filter`
The `filter` option operates similar to `custom`, accepting the same shaped object, except that it controls if the rest of the configuration should or should not be applied to an identifier.
You can use this to include or exclude specific identifiers from specific configurations.
Accepts an object with the following properties:
- `match` - true if the identifier _must_ match the `regex`, false if the identifier _must not_ match the `regex`.
- `regex` - a string that is then passed into RegExp to create a new regular expression: `new RegExp(regex)`
Alternatively, `filter` accepts a regular expression (anything accepted into `new RegExp(filter)`). In this case, it's treated as if you had passed an object with the regex and `match: true`.
#### `leadingUnderscore` / `trailingUnderscore`
The `leadingUnderscore` / `trailingUnderscore` options control whether leading/trailing underscores are considered valid. Accepts one of the following values:
- `allow` - existence of a single leading/trailing underscore is not explicitly enforced.
- `allowDouble` - existence of a double leading/trailing underscore is not explicitly enforced.
- `allowSingleOrDouble` - existence of a single or a double leading/trailing underscore is not explicitly enforced.
- `forbid` - a leading/trailing underscore is not allowed at all.
- `require` - a single leading/trailing underscore must be included.
- `requireDouble` - two leading/trailing underscores must be included.
#### `prefix` / `suffix`
The `prefix` / `suffix` options control which prefix/suffix strings must exist for the identifier. Accepts an array of strings.
If these are provided, the identifier must start with one of the provided values. For example, if you provide `{ prefix: ['Class', 'IFace', 'Type'] }`, then the following names are valid: `ClassBar`, `IFaceFoo`, `TypeBaz`, but the name `Bang` is not valid, as it contains none of the prefixes.
**Note:** As [documented above](#format-options), the prefix is trimmed before format is validated, therefore PascalCase must be used to allow variables such as `isEnabled` using the prefix `is`.
### Selector Options
- `selector` allows you to specify what types of identifiers to target.
- Accepts one or array of selectors to define an option block that applies to one or multiple selectors.
- For example, if you provide `{ selector: ['function', 'variable'] }`, then it will apply the same option to variable and function nodes.
- See [Allowed Selectors, Modifiers and Types](#allowed-selectors-modifiers-and-types) below for the complete list of allowed selectors.
- `modifiers` allows you to specify which modifiers to granularly apply to, such as the accessibility (`#private`/`private`/`protected`/`public`), or if the thing is `static`, etc.
- The name must match _all_ of the modifiers.
- For example, if you provide `{ modifiers: ['private','readonly','static'] }`, then it will only match something that is `private static readonly`, and something that is just `private` will not match.
- The following `modifiers` are allowed:
- `abstract`,`override`,`private`,`protected`,`readonly`,`static` - matches any member explicitly declared with the given modifier.
- `async` - matches any method, function, or function variable which is async via the `async` keyword (e.g. does not match functions that return promises without using `async` keyword)
- `const` - matches a variable declared as being `const` (`const x = 1`).
- `destructured` - matches a variable declared via an object destructuring pattern (`const {x, z = 2}`).
- Note that this does not match renamed destructured properties (`const {x: y, a: b = 2}`).
- `exported` - matches anything that is exported from the module.
- `global` - matches a variable/function declared in the top-level scope.
- `#private` - matches any member with a private identifier (an identifier that starts with `#`)
- `public` - matches any member that is either explicitly declared as `public`, or has no visibility modifier (i.e. implicitly public).
- `requiresQuotes` - matches any name that requires quotes as it is not a valid identifier (i.e. has a space, a dash, etc in it).
- `unused` - matches anything that is not used.
- `types` allows you to specify which types to match. This option supports simple, primitive types only (`array`,`boolean`,`function`,`number`,`string`).
- The name must match _one_ of the types.
- **_NOTE - Using this option will require that you lint with type information._**
- For example, this lets you do things like enforce that `boolean` variables are prefixed with a verb.
- The following `types` are allowed:
- `array` matches any type assignable to `Array<unknown> | null | undefined`
- `boolean` matches any type assignable to `boolean | null | undefined`
- `function` matches any type assignable to `Function | null | undefined`
- `number` matches any type assignable to `number | null | undefined`
- `string` matches any type assignable to `string | null | undefined`
The ordering of selectors does not matter. The implementation will automatically sort the selectors to ensure they match from most-specific to least specific. It will keep checking selectors in that order until it finds one that matches the name. See ["How does the rule automatically order selectors?"](#how-does-the-rule-automatically-order-selectors)
#### Allowed Selectors, Modifiers and Types
There are two types of selectors, individual selectors, and grouped selectors.
##### Individual Selectors
Individual Selectors match specific, well-defined sets. There is no overlap between each of the individual selectors.
- `accessor` - matches any accessor.
- Allowed `modifiers`: `abstract`, `override`, `private`, `protected`, `public`, `requiresQuotes`, `static`.
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`.
- `class` - matches any class declaration.
- Allowed `modifiers`: `abstract`, `exported`, `unused`.
- Allowed `types`: none.
- `classMethod` - matches any class method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors.
- Allowed `modifiers`: `abstract`, `async`, `override`, `#private`, `private`, `protected`, `public`, `requiresQuotes`, `static`.
- Allowed `types`: none.
- `classProperty` - matches any class property. Does not match properties that have direct function expression or arrow function expression values.
- Allowed `modifiers`: `abstract`, `override`, `#private`, `private`, `protected`, `public`, `readonly`, `requiresQuotes`, `static`.
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`.
- `enum` - matches any enum declaration.
- Allowed `modifiers`: `exported`, `unused`.
- Allowed `types`: none.
- `enumMember` - matches any enum member.
- Allowed `modifiers`: `requiresQuotes`.
- Allowed `types`: none.
- `function` - matches any named function declaration or named function expression.
- Allowed `modifiers`: `async`, `exported`, `global`, `unused`.
- Allowed `types`: none.
- `interface` - matches any interface declaration.
- Allowed `modifiers`: `exported`, `unused`.
- Allowed `types`: none.
- `objectLiteralMethod` - matches any object literal method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors.
- Allowed `modifiers`: `async`, `public`, `requiresQuotes`.
- Allowed `types`: none.
- `objectLiteralProperty` - matches any object literal property. Does not match properties that have direct function expression or arrow function expression values.
- Allowed `modifiers`: `public`, `requiresQuotes`.
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`.
- `parameter` - matches any function parameter. Does not match parameter properties.
- Allowed `modifiers`: `destructured`, `unused`.
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`.
- `parameterProperty` - matches any parameter property.
- Allowed `modifiers`: `private`, `protected`, `public`, `readonly`.
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`.
- `typeAlias` - matches any type alias declaration.
- Allowed `modifiers`: `exported`, `unused`.
- Allowed `types`: none.
- `typeMethod` - matches any object type method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors.
- Allowed `modifiers`: `public`, `requiresQuotes`.
- Allowed `types`: none.
- `typeParameter` - matches any generic type parameter declaration.
- Allowed `modifiers`: `unused`.
- Allowed `types`: none.
- `typeProperty` - matches any object type property. Does not match properties that have direct function expression or arrow function expression values.
- Allowed `modifiers`: `public`, `readonly`, `requiresQuotes`.
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`.
- `variable` - matches any `const` / `let` / `var` variable name.
- Allowed `modifiers`: `async`, `const`, `destructured`, `exported`, `global`, `unused`.
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`.
##### Group Selectors
Group Selectors are provided for convenience, and essentially bundle up sets of individual selectors.
- `default` - matches everything.
- Allowed `modifiers`: all modifiers.
- Allowed `types`: none.
- `memberLike` - matches the same as `accessor`, `enumMember`, `method`, `parameterProperty`, `property`.
- Allowed `modifiers`: `abstract`, `async`, `override`, `#private`, `private`, `protected`, `public`, `readonly`, `requiresQuotes`, `static`.
- Allowed `types`: none.
- `method` - matches the same as `classMethod`, `objectLiteralMethod`, `typeMethod`.
- Allowed `modifiers`: `abstract`, `async`, `override`, `#private`, `private`, `protected`, `public`, `readonly`, `requiresQuotes`, `static`.
- Allowed `types`: none.
- `property` - matches the same as `classProperty`, `objectLiteralProperty`, `typeProperty`.
- Allowed `modifiers`: `abstract`, `async`, `override`, `#private`, `private`, `protected`, `public`, `readonly`, `requiresQuotes`, `static`.
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`.
- `typeLike` - matches the same as `class`, `enum`, `interface`, `typeAlias`, `typeParameter`.
- Allowed `modifiers`: `abstract`, `unused`.
- Allowed `types`: none.
- `variableLike` - matches the same as `function`, `parameter` and `variable`.
- Allowed `modifiers`: `async`, `unused`.
- Allowed `types`: none.
## FAQ
This is a big rule, and there's a lot of docs. Here are a few clarifications that people often ask about or figure out via trial-and-error.
### How does the rule evaluate a selector?
Each selector is checked in the following way:
1. check the `filter`
1. if `filter` is omitted → skip this step.
2. if the name matches the `filter` → continue evaluating this selector.
3. if the name does not match the `filter` → skip this selector and continue to the next selector.
2. check the `selector`
1. if `selector` is one individual selector → the name's type must be of that type.
2. if `selector` is a group selector → the name's type must be one of the grouped types.
3. if `selector` is an array of selectors → apply the above for each selector in the array.
3. check the `types`
1. if `types` is omitted → skip this step.
2. if the name has a type in `types` → continue evaluating this selector.
3. if the name does not have a type in `types` → skip this selector and continue to the next selector.
A name is considered to pass the config if it:
1. Matches one selector and passes all of that selector's format checks.
2. Matches no selectors.
A name is considered to fail the config if it matches one selector and fails one that selector's format checks.
### How does the rule automatically order selectors?
Each identifier should match exactly one selector. It may match multiple group selectors - but only ever one selector.
With that in mind - the base sort order works out to be:
1. Individual Selectors
2. Grouped Selectors
3. Default Selector
Within each of these categories, some further sorting occurs based on what selector options are supplied:
1. `filter` is given the highest priority above all else.
2. `types`
3. `modifiers`
4. everything else
For example, if you provide the following config:
```ts
[
/* 1 */ { selector: 'default', format: ['camelCase'] },
/* 2 */ { selector: 'variable', format: ['snake_case'] },
/* 3 */ { selector: 'variable', types: ['boolean'], format: ['UPPER_CASE'] },
/* 4 */ { selector: 'variableLike', format: ['PascalCase'] },
];
```
Then for the code `const x = 1`, the rule will validate the selectors in the following order: `3`, `2`, `4`, `1`.
To clearly spell it out:
- (3) is tested first because it has `types` and is an individual selector.
- (2) is tested next because it is an individual selector.
- (4) is tested next as it is a grouped selector.
- (1) is tested last as it is the base default selector.
Its worth noting that whilst this order is applied, all selectors may not run on a name.
This is explained in ["How does the rule evaluate a name's format?"](#how-does-the-rule-evaluate-a-names-format)
### How does the rule evaluate a name's format?
When the format of an identifier is checked, it is checked in the following order:
1. validate leading underscore
1. validate trailing underscore
1. validate prefix
1. validate suffix
1. validate custom
1. validate format
For steps 1-4, if the identifier matches the option, the matching part will be removed.
This is done so that you can apply formats like PascalCase without worrying about prefixes or underscores causing it to not match.
One final note is that if the name were to become empty via this trimming process, it is considered to match all `format`s. An example of where this might be useful is for generic type parameters, where you want all names to be prefixed with `T`, but also want to allow for the single character `T` name.
Here are some examples to help illustrate
Name: `_IMyInterface`
Selector:
```json
{
"leadingUnderscore": "require",
"prefix": ["I"],
"format": ["UPPER_CASE", "StrictPascalCase"]
}
```
1. `name = _IMyInterface`
1. validate leading underscore
1. config is provided
1. check name → pass
1. Trim underscore → `name = IMyInterface`
1. validate trailing underscore
1. config is not provided → skip
1. validate prefix
1. config is provided
1. check name → pass
1. Trim prefix → `name = MyInterface`
1. validate suffix
1. config is not provided → skip
1. validate custom
1. config is not provided → skip
1. validate format
1. for each format...
1. `format = 'UPPER_CASE'`
1. check format → fail.
- Important to note that if you supply multiple formats - the name only needs to match _one_ of them!
1. `format = 'StrictPascalCase'`
1. check format → success.
1. **_success_**
Name: `IMyInterface`
Selector:
```json
{
"format": ["StrictPascalCase"],
"trailingUnderscore": "allow",
"custom": {
"regex": "^I[A-Z]",
"match": false
}
}
```
1. `name = IMyInterface`
1. validate leading underscore
1. config is not provided → skip
1. validate trailing underscore
1. config is provided
1. check name → pass
1. Trim underscore → `name = IMyInterface`
1. validate prefix
1. config is not provided → skip
1. validate suffix
1. config is not provided → skip
1. validate custom
1. config is provided
1. `regex = new RegExp("^I[A-Z]")`
1. `regex.test(name) === custom.match`
1. **_fail_** → report and exit
### What happens if I provide a `modifiers` to a Group Selector?
Some group selectors accept `modifiers`. For the most part these will work exactly the same as with individual selectors.
There is one exception to this in that a modifier might not apply to all individual selectors covered by a group selector.
For example - `memberLike` includes the `enumMember` selector, and it allows the `protected` modifier.
An `enumMember` can never ever be `protected`, which means that the following config will never match any `enumMember`:
```json
{
"selector": "memberLike",
"modifiers": ["protected"]
}
```
To help with matching, members that cannot specify an accessibility will always have the `public` modifier. This means that the following config will always match any `enumMember`:
```json
{
"selector": "memberLike",
"modifiers": ["public"]
}
```
## Examples
### Enforce that all variables, functions and properties follow are camelCase
```json
{
"@typescript-eslint/naming-convention": [
"error",
{ "selector": "variableLike", "format": ["camelCase"] }
]
}
```
### Enforce that private members are prefixed with an underscore
```json
{
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "memberLike",
"modifiers": ["private"],
"format": ["camelCase"],
"leadingUnderscore": "require"
}
]
}
```
### Enforce that boolean variables are prefixed with an allowed verb
**Note:** As [documented above](#format-options), the prefix is trimmed before format is validated, thus PascalCase must be used to allow variables such as `isEnabled`.
```json
{
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "variable",
"types": ["boolean"],
"format": ["PascalCase"],
"prefix": ["is", "should", "has", "can", "did", "will"]
}
]
}
```
### Enforce that all variables are either in camelCase or UPPER_CASE
```json
{
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "variable",
"format": ["camelCase", "UPPER_CASE"]
}
]
}
```
### Enforce that all const variables are in UPPER_CASE
```json
{
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "variable",
"modifiers": ["const"],
"format": ["UPPER_CASE"]
}
]
}
```
### Enforce that type parameters (generics) are prefixed with `T`
This allows you to emulate the old `generic-type-naming` rule.
```json
{
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "typeParameter",
"format": ["PascalCase"],
"prefix": ["T"]
}
]
}
```
### Enforce that interface names do not begin with an `I`
This allows you to emulate the old `interface-name-prefix` rule.
```json
{
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "interface",
"format": ["PascalCase"],
"custom": {
"regex": "^I[A-Z]",
"match": false
}
}
]
}
```
### Enforce that variable and function names are in camelCase
This allows you to lint multiple type with same pattern.
```json
{
"@typescript-eslint/naming-convention": [
"error",
{
"selector": ["variable", "function"],
"format": ["camelCase"],
"leadingUnderscore": "allow"
}
]
}
```
### Ignore properties that **_require_** quotes
Sometimes you have to use a quoted name that breaks the convention (for example, HTTP headers).
If this is a common thing in your codebase, then you have a few options.
If you simply want to allow all property names that require quotes, you can use the `requiresQuotes` modifier to match any property name that _requires_ quoting, and use `format: null` to ignore the name.
```jsonc
{
"@typescript-eslint/naming-convention": [
"error",
{
"selector": [
"classProperty",
"objectLiteralProperty",
"typeProperty",
"classMethod",
"objectLiteralMethod",
"typeMethod",
"accessor",
"enumMember"
],
"format": null,
"modifiers": ["requiresQuotes"]
}
]
}
```
If you have a small and known list of exceptions, you can use the `filter` option to ignore these specific names only:
```jsonc
{
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "property",
"format": ["strictCamelCase"],
"filter": {
// you can expand this regex to add more allowed names
"regex": "^(Property-Name-One|Property-Name-Two)$",
"match": false
}
}
]
}
```
You can use the `filter` option to ignore names with specific characters:
```jsonc
{
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "property",
"format": ["strictCamelCase"],
"filter": {
// you can expand this regex as you find more cases that require quoting that you want to allow
"regex": "[- ]",
"match": false
}
}
]
}
```
Note that there is no way to ignore any name that is quoted - only names that are required to be quoted.
This is intentional - adding quotes around a name is not an escape hatch for proper naming.
If you want an escape hatch for a specific name - you should can use an [`eslint-disable` comment](https://eslint.org/docs/user-guide/configuring#disabling-rules-with-inline-comments).
### Ignore destructured names
Sometimes you might want to allow destructured properties to retain their original name, even if it breaks your naming convention.
You can use the `destructured` modifier to match these names, and explicitly set `format: null` to apply no formatting:
```jsonc
{
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "variable",
"modifiers": ["destructured"],
"format": null
}
]
}
```
### Enforce the codebase follows ESLint's `camelcase` conventions
```json
{
"camelcase": "off",
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "default",
"format": ["camelCase"]
},
{
"selector": "variable",
"format": ["camelCase", "UPPER_CASE"]
},
{
"selector": "parameter",
"format": ["camelCase"],
"leadingUnderscore": "allow"
},
{
"selector": "memberLike",
"modifiers": ["private"],
"format": ["camelCase"],
"leadingUnderscore": "require"
},
{
"selector": "typeLike",
"format": ["PascalCase"]
}
]
}
```
## When Not To Use It
If you do not want to enforce naming conventions for anything.

View File

@@ -0,0 +1,35 @@
---
description: 'Disallow generic `Array` constructors.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-array-constructor** for documentation.
## 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<Foo>()`).
<!--tabs-->
### ❌ Incorrect
```ts
/*eslint no-array-constructor: "error"*/
Array(0, 1, 2);
new Array(0, 1, 2);
```
### ✅ Correct
```ts
/*eslint no-array-constructor: "error"*/
Array<number>(0, 1, 2);
new Array<Foo>(x, y, z);
Array(500);
new Array(someOtherArray.length);
```

View File

@@ -0,0 +1,88 @@
---
description: 'Require `.toString()` to only be called on objects which provide useful information when stringified.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-base-to-string** 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 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
<!--tabs-->
### ❌ Incorrect
```ts
// Passing an object or class instance to string concatenation:
'' + {};
class MyClass {}
const value = new MyClass();
value + '';
// Interpolation and manual .toString() calls too:
`Value: ${value}`;
({}.toString());
```
### ✅ Correct
```ts
// These types all have useful .toString()s
'Text' + true;
`Value: ${123}`;
`Arrays too: ${[1, 2, 3]}`;
(() => {}).toString();
// Defining a custom .toString class is considered acceptable
class CustomToString {
toString() {
return 'Hello, world!';
}
}
`Value: ${new CustomToString()}`;
const literalWithToString = {
toString: () => 'Hello, world!',
};
`Value: ${literalWithToString}`;
```
## Options
### `ignoredTypeNames`
A string array of type names to ignore, this is useful for types missing `toString()` (but actually has `toString()`).
There are some types missing `toString()` in old version TypeScript, like `RegExp`, `URL`, `URLSearchParams` etc.
The following patterns are considered correct with the default options `{ ignoredTypeNames: ["RegExp"] }`:
```ts
`${/regex/}`;
'' + /regex/;
/regex/.toString();
let value = /regex/;
value.toString();
let text = `${value}`;
```
## When Not To Use It
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)

View File

@@ -0,0 +1,56 @@
---
description: 'Disallow non-null assertion in locations that may be confusing.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-confusing-non-null-assertion** for documentation.
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
a! == b; // a non-null assertions(`!`) and an equals test(`==`)
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
<!--tabs-->
### ❌ Incorrect
```ts
interface Foo {
bar?: string;
num?: number;
}
const foo: Foo = getFoo();
const isEqualsBar = foo.bar! == 'hello';
const isEqualsNum = 1 + foo.num! == 2;
```
### ✅ Correct
<!-- prettier-ignore -->
```ts
interface Foo {
bar?: string;
num?: number;
}
const foo: Foo = getFoo();
const isEqualsBar = foo.bar == 'hello';
const isEqualsNum = (1 + foo.num!) == 2;
```
## When Not To Use It
If you don't care about this confusion, then you will not need this rule.
## Further Reading
- [`Issue: Easy misunderstanding: "! ==="`](https://github.com/microsoft/TypeScript/issues/37837) in [TypeScript repo](https://github.com/microsoft/TypeScript)

View File

@@ -0,0 +1,116 @@
---
description: 'Require expressions of type void to appear in statement position.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-confusing-void-expression** for documentation.
`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 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
<!--tabs-->
### ❌ Incorrect
```ts
// somebody forgot that `alert` doesn't return anything
const response = alert('Are you sure?');
console.log(alert('Are you sure?'));
// it's not obvious whether the chained promise will contain the response (fixable)
promise.then(value => window.postMessage(value));
// it looks like we are returning the result of `console.error` (fixable)
function doSomething() {
if (!somethingToDo) {
return console.error('Nothing to do!');
}
console.log('Doing a thing...');
}
```
### ✅ Correct
```ts
// just a regular void function in a statement position
alert('Hello, world!');
// this function returns a boolean value so it's ok
const response = confirm('Are you sure?');
console.log(confirm('Are you sure?'));
// now it's obvious that `postMessage` doesn't return any response
promise.then(value => {
window.postMessage(value);
});
// now it's explicit that we want to log the error and return early
function doSomething() {
if (!somethingToDo) {
console.error('Nothing to do!');
return;
}
console.log('Doing a thing...');
}
// using logical expressions for their side effects is fine
cond && console.log('true');
cond || console.error('false');
cond ? console.log('true') : console.error('false');
```
## Options
### `ignoreArrowShorthand`
It might be undesirable to wrap every arrow function shorthand expression with braces.
Especially when using Prettier formatter, which spreads such code across 3 lines instead of 1.
Examples of additional **correct** code with this option enabled:
```ts
promise.then(value => window.postMessage(value));
```
### `ignoreVoidOperator`
It might be preferable to only use some distinct syntax
to explicitly mark the confusing but valid usage of void expressions.
This option allows void expressions which are explicitly wrapped in the `void` operator.
This can help avoid confusion among other developers as long as they are made aware of this code style.
This option also changes the automatic fixes for common cases to use the `void` operator.
It also enables a suggestion fix to wrap the void expression with `void` operator for every problem reported.
Examples of additional **correct** code with this option enabled:
```ts
// now it's obvious that we don't expect any response
promise.then(value => void window.postMessage(value));
// now it's explicit that we don't want to return anything
function doSomething() {
if (!somethingToDo) {
return void console.error('Nothing to do!');
}
console.log('Doing a thing...');
}
// we are sure that we want to always log `undefined`
console.log(void alert('Hello, world!'));
```
## When Not To Use It
The return type of a function can be inspected by going to its definition or hovering over it in an IDE.
If you don't care about being explicit about the void type in actual code then don't use this rule.
Also, if you prefer concise coding style then also don't use it.

View File

@@ -0,0 +1,12 @@
---
description: 'Disallow duplicate class members.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-dupe-class-members** for documentation.
## 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.

View File

@@ -0,0 +1,50 @@
---
description: 'Disallow duplicate enum member values.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-duplicate-enum-values** for documentation.
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.
## Examples
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.
<!--tabs-->
### ❌ Incorrect
```ts
enum E {
A = 0,
B = 0,
}
```
```ts
enum E {
A = 'A',
B = 'A',
}
```
### ✅ Correct
```ts
enum E {
A = 0,
B = 1,
}
```
```ts
enum E {
A = 'A',
B = 'B',
}
```

View File

@@ -0,0 +1,12 @@
---
description: 'Disallow duplicate imports.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-duplicate-imports** for documentation.
:::danger Deprecated
This rule has been deprecated in favour of the [`import/no-duplicates`](https://github.com/import-js/eslint-plugin-import/blob/HEAD/docs/rules/no-duplicates.md) rule.
:::

View File

@@ -0,0 +1,61 @@
---
description: 'Disallow duplicate constituents of union or intersection types.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-duplicate-type-constituents** for documentation.
TypeScript supports types ("constituents") within union and intersection types being duplicates of each other.
However, developers typically expect each constituent to be unique within its intersection or union.
Duplicate values make the code overly verbose and generally reduce readability.
## Rule Details
This rule disallows duplicate union or intersection constituents.
We consider types to be duplicate if they evaluate to the same result in the type system.
For example, given `type A = string` and `type T = string | A`, this rule would flag that `A` is the same type as `string`.
<!--tabs-->
### ❌ Incorrect
```ts
type T1 = 'A' | 'A';
type T2 = A | A | B;
type T3 = { a: string } & { a: string };
type T4 = [1, 2, 3] | [1, 2, 3];
type StringA = string;
type StringB = string;
type T5 = StringA | StringB;
```
### ✅ Correct
```ts
type T1 = 'A' | 'B';
type T2 = A | B | C;
type T3 = { a: string } & { b: string };
type T4 = [1, 2, 3] | [1, 2, 3, 4];
type StringA = string;
type NumberB = number;
type T5 = StringA | NumberB;
```
## Options
### `ignoreIntersections`
When set to true, duplicate checks on intersection type constituents are ignored.
### `ignoreUnions`
When set to true, duplicate checks on union type constituents are ignored.

View File

@@ -0,0 +1,53 @@
---
description: 'Disallow using the `delete` operator on computed key expressions.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> 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.
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 youre storing collections of objects.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
// Can be replaced with the constant equivalents, such as container.aaa
delete container['aaa'];
delete container['Infinity'];
// Dynamic, difficult-to-reason-about lookups
const name = 'name';
delete container[name];
delete container[name.toUpperCase()];
```
### ✅ Correct
```ts
const container: { [i: string]: number } = {
/* ... */
};
// Constant runtime lookups by string index
delete container.aaa;
// Constants that must be accessed by []
delete container[7];
delete container['-Infinity'];
```
## When Not To Use It
When you know your keys are safe to delete, this rule can be unnecessary.
Some environments such as older browsers might not support `Map` and `Set`.
Do not consider this rule as performance advice before profiling your code's bottlenecks.
Even repeated minor performance slowdowns likely do not significantly affect your application's general perceived speed.

View File

@@ -0,0 +1,88 @@
---
description: 'Disallow empty functions.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-empty-function** for documentation.
## 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.
One example of valid TypeScript specific code that would otherwise trigger the `no-empty-function` rule is the use of [parameter properties](https://www.typescriptlang.org/docs/handbook/classes.html#parameter-properties) in constructor functions.
## Options
This rule adds the following options:
```ts
type AdditionalAllowOptionEntries =
| 'private-constructors'
| 'protected-constructors'
| 'decoratedFunctions'
| 'overrideMethods';
type AllowOptionEntries =
| BaseNoEmptyFunctionAllowOptionEntries
| AdditionalAllowOptionEntries;
interface Options extends BaseNoEmptyFunctionOptions {
allow?: Array<AllowOptionEntries>;
}
const defaultOptions: Options = {
...baseNoEmptyFunctionDefaultOptions,
allow: [],
};
```
### allow: `private-constructors`
Examples of correct code for the `{ "allow": ["private-constructors"] }` option:
```ts
class Foo {
private constructor() {}
}
```
### allow: `protected-constructors`
Examples of correct code for the `{ "allow": ["protected-constructors"] }` option:
```ts
class Foo {
protected constructor() {}
}
```
### allow: `decoratedFunctions`
Examples of correct code for the `{ "allow": ["decoratedFunctions"] }` option:
```ts
@decorator()
function foo() {}
class Foo {
@decorator()
foo() {}
}
```
### allow: `overrideMethods`
Examples of correct code for the `{ "allow": ["overrideMethods"] }` option:
```ts
abstract class Base {
protected greet(): void {
console.log('Hello!');
}
}
class Foo extends Base {
protected override greet(): void {}
}
```

View File

@@ -0,0 +1,70 @@
---
description: 'Disallow the declaration of empty interfaces.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-empty-interface** for documentation.
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
<!--tabs-->
### ❌ Incorrect
```ts
// an empty interface
interface Foo {}
// an interface with only one supertype (Bar === Foo)
interface Bar extends Foo {}
// an interface with an empty list of supertypes
interface Baz {}
```
### ✅ Correct
```ts
// an interface with any number of members
interface Foo {
name: string;
}
// same as above
interface Bar {
age: number;
}
// an interface with more than one supertype
// in this case the interface can be used as a replacement of an intersection type.
interface Baz extends Foo, Bar {}
```
<!--/tabs-->
## Options
This rule accepts a single object option with the following default configuration:
```json
{
"@typescript-eslint/no-empty-interface": [
"error",
{
"allowSingleExtends": false
}
]
}
```
- `allowSingleExtends: true` will silence warnings about extending a single interface without adding additional members
## When Not To Use It
If you don't care about having empty/meaningless interfaces, then you will not need this rule.

View File

@@ -0,0 +1,174 @@
---
description: 'Disallow the `any` type.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> 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 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.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
const age: any = 'seventeen';
```
```ts
const ages: any[] = ['seventeen'];
```
```ts
const ages: Array<any> = ['seventeen'];
```
```ts
function greet(): any {}
```
```ts
function greet(): any[] {}
```
```ts
function greet(): Array<any> {}
```
```ts
function greet(): Array<Array<any>> {}
```
```ts
function greet(param: Array<any>): string {}
```
```ts
function greet(param: Array<any>): Array<any> {}
```
### ✅ Correct
```ts
const age: number = 17;
```
```ts
const ages: number[] = [17];
```
```ts
const ages: Array<number> = [17];
```
```ts
function greet(): string {}
```
```ts
function greet(): string[] {}
```
```ts
function greet(): Array<string> {}
```
```ts
function greet(): Array<Array<string>> {}
```
```ts
function greet(param: Array<string>): string {}
```
```ts
function greet(param: Array<string>): Array<string> {}
```
## Options
### `ignoreRestArgs`
A boolean to specify if arrays from the rest operator are considered okay. `false` by default.
Examples of **incorrect** code for the `{ "ignoreRestArgs": false }` option:
```ts
/*eslint @typescript-eslint/no-explicit-any: ["error", { "ignoreRestArgs": false }]*/
function foo1(...args: any[]): void {}
function foo2(...args: readonly any[]): void {}
function foo3(...args: Array<any>): void {}
function foo4(...args: ReadonlyArray<any>): void {}
declare function bar(...args: any[]): void;
const baz = (...args: any[]) => {};
const qux = function (...args: any[]) {};
type Quux = (...args: any[]) => void;
type Quuz = new (...args: any[]) => void;
interface Grault {
(...args: any[]): void;
}
interface Corge {
new (...args: any[]): void;
}
interface Garply {
f(...args: any[]): void;
}
```
Examples of **correct** code for the `{ "ignoreRestArgs": true }` option:
```ts
/*eslint @typescript-eslint/no-explicit-any: ["error", { "ignoreRestArgs": true }]*/
function foo1(...args: any[]): void {}
function foo2(...args: readonly any[]): void {}
function foo3(...args: Array<any>): void {}
function foo4(...args: ReadonlyArray<any>): void {}
declare function bar(...args: any[]): void;
const baz = (...args: any[]) => {};
const qux = function (...args: any[]) {};
type Quux = (...args: any[]) => void;
type Quuz = new (...args: any[]) => void;
interface Grault {
(...args: any[]): void;
}
interface Corge {
new (...args: any[]): void;
}
interface Garply {
f(...args: any[]): void;
}
```
## When Not To Use It
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)

View File

@@ -0,0 +1,52 @@
---
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.
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
<!--tabs-->
### ❌ Incorrect
```ts
const foo: { bar: number } | null = null;
const bar = foo!!!.bar;
```
```ts
function foo(bar: number | undefined) {
const bar: number = bar!!!;
}
```
```ts
function foo(bar?: { n: number }) {
return bar!?.n;
}
```
### ✅ Correct
```ts
const foo: { bar: number } | null = null;
const bar = foo!.bar;
```
```ts
function foo(bar: number | undefined) {
const bar: number = bar!;
}
```
```ts
function foo(bar?: { n: number }) {
return bar?.n;
}
```

View File

@@ -0,0 +1,12 @@
---
description: 'Disallow unnecessary parentheses.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-extra-parens** for documentation.
## 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.

View File

@@ -0,0 +1,12 @@
---
description: 'Disallow unnecessary semicolons.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-extra-semi** for documentation.
## 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.

View File

@@ -0,0 +1,294 @@
---
description: 'Disallow classes used as namespaces.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-extraneous-class** for documentation.
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 `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 reports classes that have only a constructor and no fields.
Those classes can generally be replaced with a standalone function.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
class StaticConstants {
static readonly version = 42;
static isProduction() {
return process.env.NODE_ENV === 'production';
}
}
class HelloWorldLogger {
constructor() {
console.log('Hello, world!');
}
}
```
### ✅ Correct
```ts
export const version = 42;
export function isProduction() {
return process.env.NODE_ENV === 'production';
}
function logHelloWorld() {
console.log('Hello, world!');
}
```
## Alternatives
### Individual Exports (Recommended)
Instead of using a static utility class we recommend you individually export the utilities from your module.
<!--tabs-->
#### ❌ Incorrect
```ts
export class Utilities {
static util1() {
return Utilities.util3();
}
static util2() {
/* ... */
}
static util3() {
/* ... */
}
}
```
#### ✅ Correct
```ts
export function util1() {
return util3();
}
export function util2() {
/* ... */
}
export function util3() {
/* ... */
}
```
### Namespace Imports (Not Recommended)
If you strongly prefer to have all constructs from a module available as properties of a single object, you can `import * as` the module.
This is known as a "namespace import".
Namespace imports are sometimes preferable because they keep all properties nested and don't need to be changed as you start or stop using various properties from the module.
However, namespace imports are impacted by these downsides:
- They also don't play as well with tree shaking in modern bundlers
- They require a name prefix before each property's usage
<!--tabs-->
#### ❌ Incorrect
```ts
// utilities.ts
export class Utilities {
static sayHello() {
console.log('Hello, world!');
}
}
// consumers.ts
import { Utilities } from './utilities';
Utilities.sayHello();
```
#### ⚠️ Namespace Imports
```ts
// utilities.ts
export function sayHello() {
console.log('Hello, world!');
}
// consumers.ts
import * as utilities from './utilities';
utilities.sayHello();
```
#### ✅ Standalone Imports
```ts
// utilities.ts
export function sayHello() {
console.log('Hello, world!');
}
// consumers.ts
import { sayHello } from './utilities';
sayHello();
```
### Notes on Mutating Variables
One case you need to be careful of is exporting mutable variables.
While class properties can be mutated externally, exported variables are always constant.
This means that importers can only ever read the first value they are assigned and cannot write to the variables.
Needing to write to an exported variable is very rare and is generally considered a code smell.
If you do need it you can accomplish it using getter and setter functions:
<!--tabs-->
#### ❌ Incorrect
```ts
export class Utilities {
static mutableCount = 1;
static incrementCount() {
Utilities.mutableCount += 1;
}
}
```
#### ✅ Correct
```ts
let mutableCount = 1;
export function getMutableCount() {
return mutableField;
}
export function incrementCount() {
mutableField += 1;
}
```
## Options
This rule normally bans classes that are empty (have no constructor or fields).
The rule's options each add an exemption for a specific type of class.
### `allowConstructorOnly`
`allowConstructorOnly` adds an exemption for classes that have only a constructor and no fields.
<!--tabs-->
#### ❌ Incorrect
```ts
class NoFields {}
```
#### ✅ Correct
```ts
class NoFields {
constructor() {
console.log('Hello, world!');
}
}
```
### `allowEmpty`
The `allowEmpty` option adds an exemption for classes that are entirely empty.
<!--tabs-->
#### ❌ Incorrect
```ts
class NoFields {
constructor() {
console.log('Hello, world!');
}
}
```
#### ✅ Correct
```ts
class NoFields {}
```
### `allowStaticOnly`
The `allowStaticOnly` option adds an exemption for classes that only contain static members.
:::caution
We strongly recommend against the `allowStaticOnly` exemption.
It works against this rule's primary purpose of discouraging classes used only for static members.
:::
<!--tabs-->
#### ❌ Incorrect
```ts
class EmptyClass {}
```
#### ✅ Correct
```ts
class NotEmptyClass {
static version = 42;
}
```
### `allowWithDecorator`
The `allowWithDecorator` option adds an exemption for classes that contain a member decorated with a `@` decorator.
<!--tabs-->
#### ❌ Incorrect
```ts
class Constants {
static readonly version = 42;
}
```
#### ✅ Correct
```ts
class Constants {
@logOnRead()
static readonly version = 42;
}
```
## When Not To Use It
You can disable this rule if you are unable -or unwilling- to switch off using classes as namespaces.

View File

@@ -0,0 +1,106 @@
---
description: 'Require Promise-like statements to be handled appropriately.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> 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
- `return`ing it
- Calling its `.then()` with two arguments
- Calling its `.catch()` with one argument
:::tip
`no-floating-promises` only detects unhandled Promise _statements_.
See [`no-misused-promises`](./no-misused-promises.md) for detecting code that provides Promises to _logical_ locations such as if statements.
:::
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
const promise = new Promise((resolve, reject) => resolve('value'));
promise;
async function returnsPromise() {
return 'value';
}
returnsPromise().then(() => {});
Promise.reject('value').catch();
Promise.reject('value').finally();
```
### ✅ Correct
```ts
const promise = new Promise((resolve, reject) => resolve('value'));
await promise;
async function returnsPromise() {
return 'value';
}
returnsPromise().then(
() => {},
() => {},
);
Promise.reject('value').catch(() => {});
Promise.reject('value').finally(() => {});
```
## Options
### `ignoreVoid`
This allows you to stop the rule reporting promises consumed with void operator.
This can be a good way to explicitly mark a promise as intentionally not awaited.
Examples of **correct** code for this rule with `{ ignoreVoid: true }`:
```ts
async function returnsPromise() {
return 'value';
}
void returnsPromise();
void Promise.reject('value');
```
With this option set to `true`, and if you are using `no-void`, you should turn on the [`allowAsStatement`](https://eslint.org/docs/rules/no-void#allowasstatement) option.
### `ignoreIIFE`
This allows you to skip checking of async IIFEs (Immediately Invocated function Expressions).
Examples of **correct** code for this rule with `{ ignoreIIFE: true }`:
```ts
await(async function () {
await res(1);
})();
(async function () {
await res(1);
})();
```
## When Not To Use It
If you do not use Promise-like values in your codebase, or want to allow them to remain unhandled.
## Related To
- [`no-misused-promises`](./no-misused-promises.md)

View File

@@ -0,0 +1,56 @@
---
description: 'Disallow iterating over an array with a for-in loop.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-for-in-array** for documentation.
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.
## Examples
<!--tabs-->
### ❌ Incorrect
```js
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
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);
}
```
## When Not To Use It
If you want to iterate through a loop using the indices in an array as strings, you can turn off this rule.

View File

@@ -0,0 +1,73 @@
---
description: 'Disallow usage of the implicit `any` type in catch clauses.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-implicit-any-catch** for documentation.
:::danger Deprecated
This rule has been deprecated as TypeScript versions >=4 includes a `useUnknownInCatchVariables` compiler option with the same check.
:::
TypeScript 4.0 added support for adding an explicit `any` or `unknown` type annotation on a catch clause variable.
By default, TypeScript will type a catch clause variable as `any`, so explicitly annotating it as `unknown` can add a lot of safety to your codebase.
The `noImplicitAny` flag in TypeScript does not cover this for backwards compatibility reasons, however you can use `useUnknownInCatchVariables` (part of `strict`) instead of this rule.
## DEPRECATED
## Examples
This rule requires an explicit type to be declared on a catch clause variable.
<!--tabs-->
### ❌ Incorrect
```ts
try {
// ...
} catch (e) {
// ...
}
```
### ✅ Correct
<!-- TODO: prettier currently removes the type annotations, re-enable this once prettier is updated -->
<!-- prettier-ignore-start -->
```ts
try {
// ...
} catch (e: unknown) {
// ...
}
```
<!-- prettier-ignore-end -->
## Options
### `allowExplicitAny`
The follow is is **_not_** considered a warning with `{ allowExplicitAny: true }`
```ts
try {
// ...
} catch (e: any) {
// ...
}
```
## When Not To Use It
If you are not using TypeScript 4.0 (or greater), then you will not be able to use this rule, annotations on catch clauses is not supported.
## Further Reading
- [TypeScript 4.0 Release Notes](https://devblogs.microsoft.com/typescript/announcing-typescript-4-0/#unknown-on-catch)

View File

@@ -0,0 +1,101 @@
---
description: 'Disallow the use of `eval()`-like methods.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-implied-eval** for documentation.
It's considered a good practice to avoid using `eval()`. There are security and performance implications involved with doing so, which is why many linters recommend disallowing `eval()`. However, there are some other ways to pass a string and have it interpreted as JavaScript code that have similar concerns.
The first is using `setTimeout()`, `setInterval()`, `setImmediate` or `execScript()` (Internet Explorer only), all of which can accept a string of code as their first argument
```ts
setTimeout('alert(`Hi!`);', 100);
```
or using `new Function()`
```ts
const fn = new Function('a', 'b', 'return a + b');
```
This is considered an implied `eval()` because a string of code is
passed in to be interpreted. The same can be done with `setInterval()`, `setImmediate()` and `execScript()`. All interpret the JavaScript code in the global scope.
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()`.
## Examples
This rule aims to eliminate implied `eval()` through the use of `new Function()`, `setTimeout()`, `setInterval()`, `setImmediate()` or `execScript()`.
<!--tabs-->
### ❌ Incorrect
```ts
/* eslint @typescript-eslint/no-implied-eval: "error" */
setTimeout('alert(`Hi!`);', 100);
setInterval('alert(`Hi!`);', 100);
setImmediate('alert(`Hi!`)');
execScript('alert(`Hi!`)');
window.setTimeout('count = 5', 10);
window.setInterval('foo = bar', 10);
const fn = '() = {}';
setTimeout(fn, 100);
const fn = () => {
return 'x = 10';
};
setTimeout(fn(), 100);
const fn = new Function('a', 'b', 'return a + b');
```
### ✅ Correct
```ts
/* eslint @typescript-eslint/no-implied-eval: "error" */
setTimeout(function () {
alert('Hi!');
}, 100);
setInterval(function () {
alert('Hi!');
}, 100);
setImmediate(function () {
alert('Hi!');
});
execScript(function () {
alert('Hi!');
});
const fn = () => {};
setTimeout(fn, 100);
const foo = {
fn: function () {},
};
setTimeout(foo.fn, 100);
setTimeout(foo.fn.bind(this), 100);
class Foo {
static fn = () => {};
}
setTimeout(Foo.fn, 100);
```
## When Not To Use It
If you want to allow `new Function()` or `setTimeout()`, `setInterval()`, `setImmediate()` and `execScript()` with string arguments, then you can safely disable this rule.

View File

@@ -0,0 +1,75 @@
---
description: 'Enforce the use of top-level import type qualifier when an import only has specifiers with inline type qualifiers.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-import-type-side-effects** for documentation.
The [`--verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax) compiler option causes TypeScript to do simple and predictable transpilation on import declarations.
Namely, it completely removes import declarations with a top-level `type` qualifier, and it removes any import specifiers with an inline `type` qualifier.
The latter behavior does have one potentially surprising effect in that in certain cases TS can leave behind a "side effect" import at runtime:
```ts
import { type A, type B } from 'mod';
// is transpiled to
import {} from 'mod';
// which is the same as
import 'mod';
```
For the rare case of needing to import for side effects, this may be desirable - but for most cases you will not want to leave behind an unnecessary side effect import.
## Examples
This rule enforces that you use a top-level `type` qualifier for imports when it only imports specifiers with an inline `type` qualifier
<!--tabs-->
### ❌ Incorrect
```ts
import { type A } from 'mod';
import { type A as AA } from 'mod';
import { type A, type B } from 'mod';
import { type A as AA, type B as BB } from 'mod';
```
### ✅ Correct
```ts
import type { A } from 'mod';
import type { A as AA } from 'mod';
import type { A, B } from 'mod';
import type { A as AA, B as BB } from 'mod';
import T from 'mod';
import type T from 'mod';
import * as T from 'mod';
import type * as T from 'mod';
import { T } from 'mod';
import type { T } from 'mod';
import { T, U } from 'mod';
import type { T, U } from 'mod';
import { type T, U } from 'mod';
import { T, type U } from 'mod';
import type T, { U } from 'mod';
import T, { type U } from 'mod';
```
## When Not To Use It
- If you want to leave behind side effect imports, then you shouldn't use this rule.
- If you're not using TypeScript 5.0's `verbatimModuleSyntax` option, then you don't need this rule.
## Related To
- [`consistent-type-imports`](./consistent-type-imports.md)
- [`import/consistent-type-specifier-style`](https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/consistent-type-specifier-style.md)
- [`import/no-duplicates` with `{"prefer-inline": true}`](https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-duplicates.md#inline-type-imports)

View File

@@ -0,0 +1,103 @@
---
description: 'Disallow explicit type declarations for variables or parameters initialized to a number, string, or boolean.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-inferrable-types** for documentation.
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
<!--tabs-->
### ❌ Incorrect
```ts
const a: bigint = 10n;
const a: bigint = BigInt(10);
const a: boolean = !0;
const a: boolean = Boolean(null);
const a: boolean = true;
const a: null = null;
const a: number = 10;
const a: number = Infinity;
const a: number = NaN;
const a: number = Number('1');
const a: RegExp = /a/;
const a: RegExp = new RegExp('a');
const a: string = `str`;
const a: string = String(1);
const a: symbol = Symbol('a');
const a: undefined = undefined;
const a: undefined = void someValue;
class Foo {
prop: number = 5;
}
function fn(a: number = 5, b: boolean = true) {}
```
### ✅ Correct
```ts
const a = 10n;
const a = BigInt(10);
const a = !0;
const a = Boolean(null);
const a = true;
const a = null;
const a = 10;
const a = Infinity;
const a = NaN;
const a = Number('1');
const a = /a/;
const a = new RegExp('a');
const a = `str`;
const a = String(1);
const a = Symbol('a');
const a = undefined;
const a = void someValue;
class Foo {
prop = 5;
}
function fn(a = 5, b = true) {}
```
<!--/tabs-->
## Options
### `ignoreParameters`
When set to true, the following pattern is considered valid:
```ts
function foo(a: number = 5, b: boolean = true) {
// ...
}
```
### `ignoreProperties`
When set to true, the following pattern is considered valid:
```ts
class Foo {
prop: number = 5;
}
```
## When Not To Use It
If you do not want to enforce inferred types.
## Further Reading
TypeScript [Inference](https://www.typescriptlang.org/docs/handbook/type-inference.html)

View File

@@ -0,0 +1,12 @@
---
description: 'Disallow `this` keywords outside of classes or class-like objects.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-invalid-this** for documentation.
## 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.

View File

@@ -0,0 +1,113 @@
---
description: 'Disallow `void` type outside of generic or return types.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-invalid-void-type** for documentation.
`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.
> 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
<!--tabs-->
### ❌ Incorrect
```ts
type PossibleValues = string | number | void;
type MorePossibleValues = string | ((number & any) | (string | void));
function logSomething(thing: void) {}
function printArg<T = void>(arg: T) {}
logAndReturn<void>(undefined);
interface Interface {
lambda: () => void;
prop: void;
}
class MyClass {
private readonly propName: void;
}
```
### ✅ Correct
```ts
type NoOp = () => void;
function noop(): void {}
let trulyUndefined = void 0;
async function promiseMeSomething(): Promise<void> {}
type stillVoid = void | never;
```
## Options
### `allowInGenericTypeArguments`
This option lets you control if `void` can be used as a valid value for generic type parameters.
Alternatively, you can provide an array of strings which whitelist which types may accept `void` as a generic type parameter.
Any types considered valid by this option will be considered valid as part of a union type with `void`.
This option is `true` by default.
The following patterns are considered warnings with `{ allowInGenericTypeArguments: false }`:
```ts
logAndReturn<void>(undefined);
let voidPromise: Promise<void> = new Promise<void>(() => {});
let voidMap: Map<string, void> = new Map<string, void>();
```
The following patterns are considered warnings with `{ allowInGenericTypeArguments: ['Ex.Mx.Tx'] }`:
```ts
logAndReturn<void>(undefined);
type NotAllowedVoid1 = Mx.Tx<void>;
type NotAllowedVoid2 = Tx<void>;
type NotAllowedVoid3 = Promise<void>;
```
The following patterns are not considered warnings with `{ allowInGenericTypeArguments: ['Ex.Mx.Tx'] }`:
```ts
type AllowedVoid = Ex.Mx.Tx<void>;
type AllowedVoidUnion = void | Ex.Mx.Tx<void>;
```
### `allowAsThisParameter`
This option allows specifying a `this` parameter of a function to be `void` when set to `true`.
This pattern can be useful to explicitly label function types that do not use a `this` argument. [See the TypeScript docs for more information](https://www.typescriptlang.org/docs/handbook/functions.html#this-parameters-in-callbacks).
This option is `false` by default.
The following patterns are considered warnings with `{ allowAsThisParameter: false }` but valid with `{ allowAsThisParameter: true }`:
```ts
function doThing(this: void) {}
class Example {
static helper(this: void) {}
callback(this: void) {}
}
```
## When Not To Use It
If you don't care about if `void` is used with other types,
or in invalid places, then you don't need this rule.

View File

@@ -0,0 +1,12 @@
---
description: 'Disallow function declarations that contain unsafe references inside loop statements.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-loop-func** for documentation.
## 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.

View File

@@ -0,0 +1,12 @@
---
description: 'Disallow literal numbers that lose precision.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-loss-of-precision** for documentation.
## 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).

View File

@@ -0,0 +1,131 @@
---
description: 'Disallow magic numbers.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-magic-numbers** for documentation.
## Examples
This rule extends the base [`eslint/no-magic-numbers`](https://eslint.org/docs/rules/no-magic-numbers) rule.
It adds support for:
- numeric literal types (`type T = 1`),
- `enum` members (`enum Foo { bar = 1 }`),
- `readonly` class properties (`class Foo { readonly bar = 1 }`).
## Options
This rule adds the following options:
```ts
interface Options extends BaseNoMagicNumbersOptions {
ignoreEnums?: boolean;
ignoreNumericLiteralTypes?: boolean;
ignoreReadonlyClassProperties?: boolean;
ignoreTypeIndexes?: boolean;
}
const defaultOptions: Options = {
...baseNoMagicNumbersDefaultOptions,
ignoreEnums: false,
ignoreNumericLiteralTypes: false,
ignoreReadonlyClassProperties: false,
ignoreTypeIndexes: false,
};
```
### `ignoreEnums`
A boolean to specify if enums used in TypeScript are considered okay. `false` by default.
Examples of **incorrect** code for the `{ "ignoreEnums": false }` option:
```ts
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreEnums": false }]*/
enum foo {
SECOND = 1000,
}
```
Examples of **correct** code for the `{ "ignoreEnums": true }` option:
```ts
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreEnums": true }]*/
enum foo {
SECOND = 1000,
}
```
### `ignoreNumericLiteralTypes`
A boolean to specify if numbers used in TypeScript numeric literal types are considered okay. `false` by default.
Examples of **incorrect** code for the `{ "ignoreNumericLiteralTypes": false }` option:
```ts
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreNumericLiteralTypes": false }]*/
type SmallPrimes = 2 | 3 | 5 | 7 | 11;
```
Examples of **correct** code for the `{ "ignoreNumericLiteralTypes": true }` option:
```ts
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreNumericLiteralTypes": true }]*/
type SmallPrimes = 2 | 3 | 5 | 7 | 11;
```
### `ignoreReadonlyClassProperties`
Examples of **incorrect** code for the `{ "ignoreReadonlyClassProperties": false }` option:
```ts
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreReadonlyClassProperties": false }]*/
class Foo {
readonly A = 1;
readonly B = 2;
public static readonly C = 1;
static readonly D = 1;
}
```
Examples of **correct** code for the `{ "ignoreReadonlyClassProperties": true }` option:
```ts
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreReadonlyClassProperties": true }]*/
class Foo {
readonly A = 1;
readonly B = 2;
public static readonly C = 1;
static readonly D = 1;
}
```
### `ignoreTypeIndexes`
A boolean to specify if numbers used to index types are okay. `false` by default.
Examples of **incorrect** code for the `{ "ignoreTypeIndexes": false }` option:
```ts
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreTypeIndexes": false }]*/
type Foo = Bar[0];
type Baz = Parameters<Foo>[2];
```
Examples of **correct** code for the `{ "ignoreTypeIndexes": true }` option:
```ts
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreTypeIndexes": true }]*/
type Foo = Bar[0];
type Baz = Parameters<Foo>[2];
```

View File

@@ -0,0 +1,47 @@
---
description: 'Disallow the `void` operator except when used to discard a value.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-meaningless-void-operator** for documentation.
`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.
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`.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
void (() => {})();
function foo() {}
void foo();
```
### ✅ Correct
```ts
(() => {})();
function foo() {}
foo(); // nothing to discard
function bar(x: number) {
void x; // discarding a number
return 2;
}
void bar(); // discarding a number
```
## Options
`checkNever: true` will suggest removing `void` when the argument has type `never`.

View File

@@ -0,0 +1,46 @@
---
description: 'Enforce valid definition of `new` and `constructor`.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-misused-new** for documentation.
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
<!--tabs-->
### ❌ Incorrect
```ts
declare class C {
new(): C;
}
interface I {
new (): I;
constructor(): void;
}
```
### ✅ Correct
```ts
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.

View File

@@ -0,0 +1,245 @@
---
description: 'Disallow Promises in places not designed to handle them.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-misused-promises** for documentation.
This rule forbids providing Promises to logical locations such as if statements in places where the TypeScript compiler allows them but they are not handled properly.
These situations can often arise due to a missing `await` keyword or just a misunderstanding of the way async
functions are handled/awaited.
:::tip
`no-misused-promises` only detects code that provides Promises to incorrect _logical_ locations.
See [`no-floating-promises`](./no-floating-promises.md) for detecting unhandled Promise _statements_.
:::
## Options
### `"checksConditionals"`
If you don't want to check conditionals, you can configure the rule with `"checksConditionals": false`:
```json
{
"@typescript-eslint/no-misused-promises": [
"error",
{
"checksConditionals": false
}
]
}
```
Doing so prevents the rule from looking at code like `if (somePromise)`.
Examples of code for this rule with `checksConditionals: true`:
<!--tabs-->
#### ❌ 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
}
```
<!--/tabs-->
### `"checksVoidReturn"`
Likewise, if you don't want functions that return promises where a void return is
expected to be checked, your configuration will look like this:
```json
{
"@typescript-eslint/no-misused-promises": [
"error",
{
"checksVoidReturn": false
}
]
}
```
You can disable selective parts of the `checksVoidReturn` option by providing an object that disables specific checks.
The following options are supported:
- `arguments`: Disables checking an asynchronous function passed as argument where the parameter type expects a function that returns `void`
- `attributes`: Disables checking an asynchronous function passed as a JSX attribute expected to be a function that returns `void`
- `properties`: Disables checking an asynchronous function passed as an object property expected to be a function that returns `void`
- `returns`: Disables checking an asynchronous function returned in a function whose return type is a function that returns `void`
- `variables`: Disables checking an asynchronous function used as a variable whose return type is a function that returns `void`
For example, if you don't mind that passing a `() => Promise<void>` to a `() => void` parameter or JSX attribute can lead to a floating unhandled Promise:
```json
{
"@typescript-eslint/no-misused-promises": [
"error",
{
"checksVoidReturn": {
"arguments": false,
"attributes": false
}
}
]
}
```
Examples of code for this rule with `checksVoidReturn: true`:
<!--tabs-->
#### ❌ Incorrect
```ts
[1, 2, 3].forEach(async value => {
await doSomething(value);
});
new Promise(async (resolve, reject) => {
await doSomething();
resolve();
});
const eventEmitter = new EventEmitter();
eventEmitter.on('some-event', async () => {
synchronousCall();
await doSomething();
otherSynchronousCall();
});
```
#### ✅ Correct
```ts
// for-of puts `await` in outer context
for (const value of [1, 2, 3]) {
await doSomething(value);
}
// If outer context is not `async`, handle error explicitly
Promise.all(
[1, 2, 3].map(async value => {
await doSomething(value);
}),
).catch(handleError);
// Use an async IIFE wrapper
new Promise((resolve, reject) => {
// combine with `void` keyword to tell `no-floating-promises` rule to ignore unhandled rejection
void (async () => {
await doSomething();
resolve();
})();
});
// Name the async wrapper to call it later
const eventEmitter = new EventEmitter();
eventEmitter.on('some-event', () => {
const handler = async () => {
await doSomething();
otherSynchronousCall();
};
try {
synchronousCall();
} catch (err) {
handleSpecificError(err);
}
handler().catch(handleError);
});
```
<!--/tabs-->
### `"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`:
<!--tabs-->
#### ❌ Incorrect
```ts
const getData = () => someAsyncOperation({ myArg: 'foo' });
return { foo: 42, ...getData() };
const getData2 = async () => {
await someAsyncOperation({ myArg: 'foo' });
};
return { foo: 42, ...getData2() };
```
#### ✅ Correct
```ts
const getData = () => someAsyncOperation({ myArg: 'foo' });
return { foo: 42, ...(await getData()) };
const getData2 = async () => {
await someAsyncOperation({ myArg: 'foo' });
};
return { foo: 42, ...(await getData2()) };
```
<!--tabs-->
## When Not To Use It
If you do not use Promises in your codebase or are not concerned with possible
misuses of them outside of what the TypeScript compiler will check.
## Further Reading
- [TypeScript void function assignability](https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-functions-returning-non-void-assignable-to-function-returning-void)
## Related To
- [`no-floating-promises`](./no-floating-promises.md)

View File

@@ -0,0 +1,88 @@
---
description: 'Disallow enums from having both number and string members.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-mixed-enums** for documentation.
TypeScript enums are allowed to assign numeric or string values to their members.
Most enums contain either all numbers or all strings, but in theory you can mix-and-match within the same enum.
Mixing enum member types is generally considered confusing and a bad practice.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
enum Status {
Unknown,
Closed = 1,
Open = 'open',
}
```
### ✅ Correct (Explicit Numbers)
```ts
enum Status {
Unknown = 0,
Closed = 1,
Open = 2,
}
```
### ✅ Correct (Implicit Numbers)
```ts
enum Status {
Unknown,
Closed,
Open,
}
```
### ✅ Correct (Strings)
```ts
enum Status {
Unknown = 'unknown',
Closed = 'closed',
Open = 'open',
}
```
## Iteration Pitfalls of Mixed Enum Member Values
Enum values may be iterated over using `Object.entries`/`Object.keys`/`Object.values`.
If all enum members are strings, the number of items will match the number of enum members:
```ts
enum Status {
Closed = 'closed',
Open = 'open',
}
// ['closed', 'open']
Object.values(Status);
```
But if the enum contains members that are initialized with numbers -including implicitly initialized numbers— then iteration over that enum will include those numbers as well:
```ts
enum Status {
Unknown,
Closed = 1,
Open = 'open',
}
// ["Unknown", "Closed", 0, 1, "open"]
Object.values(Status);
```
## When Not To Use It
If you don't mind the confusion of mixed enum member values and don't iterate over enums, you can safely disable this rule.

View File

@@ -0,0 +1,129 @@
---
description: 'Disallow TypeScript namespaces.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-namespace** for documentation.
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 does not report on the use of TypeScript module declarations to describe external APIs (`declare module 'foo' {}`).
## Examples
Examples of code with the default options:
<!--tabs-->
### ❌ Incorrect
```ts
module foo {}
namespace foo {}
declare module foo {}
declare namespace foo {}
```
### ✅ Correct
```ts
declare module 'foo' {}
// anything inside a d.ts file
```
<!--/tabs-->
## Options
### `allowDeclarations`
Examples of code with the `{ "allowDeclarations": true }` option:
<!--tabs-->
#### ❌ Incorrect
```ts
module foo {}
namespace foo {}
```
#### ✅ Correct
```ts
declare module 'foo' {}
declare module foo {}
declare namespace foo {}
declare global {
namespace foo {}
}
declare module foo {
namespace foo {}
}
```
<!--/tabs-->
Examples of code for the `{ "allowDeclarations": false }` option:
<!--tabs-->
#### ❌ Incorrect
```ts
module foo {}
namespace foo {}
declare module foo {}
declare namespace foo {}
```
#### ✅ Correct
```ts
declare module 'foo' {}
```
### `allowDefinitionFiles`
Examples of code for the `{ "allowDefinitionFiles": true }` option:
<!--tabs-->
#### ❌ Incorrect
```ts
// if outside a d.ts file
module foo {}
namespace foo {}
// if outside a d.ts file and allowDeclarations = false
module foo {}
namespace foo {}
declare module foo {}
declare namespace foo {}
```
#### ✅ Correct
```ts
declare module 'foo' {}
// anything inside a d.ts file
```
## When Not To Use It
If you are using the ES2015 module syntax, then you will not need this rule.
## Further Reading
- [Modules](https://www.typescriptlang.org/docs/handbook/modules.html)
- [Namespaces](https://www.typescriptlang.org/docs/handbook/namespaces.html)
- [Namespaces and Modules](https://www.typescriptlang.org/docs/handbook/namespaces-and-modules.html)

View File

@@ -0,0 +1,49 @@
---
description: 'Disallow non-null assertions in the left operand of a nullish coalescing operator.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-non-null-asserted-nullish-coalescing** for documentation.
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.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
foo! ?? bar;
foo.bazz! ?? bar;
foo!.bazz! ?? bar;
foo()! ?? bar;
let x!: string;
x! ?? '';
let x: string;
x = foo();
x! ?? '';
```
### ✅ Correct
```ts
foo ?? bar;
foo ?? bar!;
foo!.bazz ?? bar;
foo!.bazz ?? bar!;
foo() ?? bar;
// This is considered correct code because there's no way for the user to satisfy it.
let x: string;
x! ?? '';
```
## Further Reading
- [TypeScript 3.7 Release Notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html)
- [Nullish Coalescing Proposal](https://github.com/tc39/proposal-nullish-coalescing)

View File

@@ -0,0 +1,35 @@
---
description: 'Disallow non-null assertions after an optional chain expression.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-non-null-asserted-optional-chain** for documentation.
`?.` 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.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
foo?.bar!;
foo?.bar()!;
```
### ✅ Correct
```ts
foo?.bar;
foo?.bar();
```
## Further Reading
- [TypeScript 3.7 Release Notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html)
- [Optional Chaining Proposal](https://github.com/tc39/proposal-optional-chaining/)

View File

@@ -0,0 +1,42 @@
---
description: 'Disallow non-null assertions using the `!` postfix operator.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> 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
<!--tabs-->
### ❌ Incorrect
```ts
interface Example {
property?: string;
}
declare const example: Example;
const includesBaz = example.property!.includes('baz');
```
### ✅ Correct
```ts
interface Example {
property?: string;
}
declare const example: Example;
const includesBaz = example.property?.includes('baz') ?? false;
```
## When Not To Use It
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.

View File

@@ -0,0 +1,406 @@
---
description: 'Disallow the use of parameter properties in class constructors.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-parameter-properties** for documentation.
:::danger Deprecated
This rule has been deprecated in favour of the equivalent, better named [`parameter-properties`](./parameter-properties.md) rule.
:::
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.
## Options
This rule, in its default state, does not require any argument and would completely disallow the use of parameter properties.
If you would like to allow certain types of parameter properties then you may pass an object with the following options:
- `allows`, an array containing one or more of the allowed modifiers. Valid values are:
- `readonly`, allows **readonly** parameter properties.
- `private`, allows **private** parameter properties.
- `protected`, allows **protected** parameter properties.
- `public`, allows **public** parameter properties.
- `private readonly`, allows **private readonly** parameter properties.
- `protected readonly`, allows **protected readonly** parameter properties.
- `public readonly`, allows **public readonly** parameter properties.
### default
Examples of code for this rule with no options at all:
<!--tabs-->
#### ❌ Incorrect
```ts
class Foo {
constructor(readonly name: string) {}
}
class Foo {
constructor(private name: string) {}
}
class Foo {
constructor(protected name: string) {}
}
class Foo {
constructor(public name: string) {}
}
class Foo {
constructor(private readonly name: string) {}
}
class Foo {
constructor(protected readonly name: string) {}
}
class Foo {
constructor(public readonly name: string) {}
}
```
#### ✅ Correct
```ts
class Foo {
constructor(name: string) {}
}
```
### readonly
Examples of code for the `{ "allows": ["readonly"] }` options:
<!--tabs-->
#### ❌ Incorrect
```ts
class Foo {
constructor(private name: string) {}
}
class Foo {
constructor(protected name: string) {}
}
class Foo {
constructor(public name: string) {}
}
class Foo {
constructor(private readonly name: string) {}
}
class Foo {
constructor(protected readonly name: string) {}
}
class Foo {
constructor(public readonly name: string) {}
}
```
#### ✅ Correct
```ts
class Foo {
constructor(name: string) {}
}
class Foo {
constructor(readonly name: string) {}
}
```
### private
Examples of code for the `{ "allows": ["private"] }` options:
<!--tabs-->
#### ❌ Incorrect
```ts
class Foo {
constructor(readonly name: string) {}
}
class Foo {
constructor(protected name: string) {}
}
class Foo {
constructor(public name: string) {}
}
class Foo {
constructor(private readonly name: string) {}
}
class Foo {
constructor(protected readonly name: string) {}
}
class Foo {
constructor(public readonly name: string) {}
}
```
#### ✅ Correct
```ts
class Foo {
constructor(name: string) {}
}
class Foo {
constructor(private name: string) {}
}
```
### protected
Examples of code for the `{ "allows": ["protected"] }` options:
<!--tabs-->
#### ❌ Incorrect
```ts
class Foo {
constructor(readonly name: string) {}
}
class Foo {
constructor(private name: string) {}
}
class Foo {
constructor(public name: string) {}
}
class Foo {
constructor(private readonly name: string) {}
}
class Foo {
constructor(protected readonly name: string) {}
}
class Foo {
constructor(public readonly name: string) {}
}
```
#### ✅ Correct
```ts
class Foo {
constructor(name: string) {}
}
class Foo {
constructor(protected name: string) {}
}
```
### public
Examples of code for the `{ "allows": ["public"] }` options:
<!--tabs-->
#### ❌ Incorrect
```ts
class Foo {
constructor(readonly name: string) {}
}
class Foo {
constructor(private name: string) {}
}
class Foo {
constructor(protected name: string) {}
}
class Foo {
constructor(private readonly name: string) {}
}
class Foo {
constructor(protected readonly name: string) {}
}
class Foo {
constructor(public readonly name: string) {}
}
```
#### ✅ Correct
```ts
class Foo {
constructor(name: string) {}
}
class Foo {
constructor(public name: string) {}
}
```
### private readonly
Examples of code for the `{ "allows": ["private readonly"] }` options:
<!--tabs-->
#### ❌ Incorrect
```ts
class Foo {
constructor(readonly name: string) {}
}
class Foo {
constructor(private name: string) {}
}
class Foo {
constructor(protected name: string) {}
}
class Foo {
constructor(public name: string) {}
}
class Foo {
constructor(protected readonly name: string) {}
}
class Foo {
constructor(public readonly name: string) {}
}
```
#### ✅ Correct
```ts
class Foo {
constructor(name: string) {}
}
class Foo {
constructor(private readonly name: string) {}
}
```
### protected readonly
Examples of code for the `{ "allows": ["protected readonly"] }` options:
<!--tabs-->
#### ❌ Incorrect
```ts
class Foo {
constructor(readonly name: string) {}
}
class Foo {
constructor(private name: string) {}
}
class Foo {
constructor(protected name: string) {}
}
class Foo {
constructor(public name: string) {}
}
class Foo {
constructor(private readonly name: string) {}
}
class Foo {
constructor(public readonly name: string) {}
}
```
#### ✅ Correct
```ts
class Foo {
constructor(name: string) {}
}
class Foo {
constructor(protected readonly name: string) {}
}
```
### public readonly
Examples of code for the `{ "allows": ["public readonly"] }` options:
<!--tabs-->
#### ❌ Incorrect
```ts
class Foo {
constructor(readonly name: string) {}
}
class Foo {
constructor(private name: string) {}
}
class Foo {
constructor(protected name: string) {}
}
class Foo {
constructor(public name: string) {}
}
class Foo {
constructor(private readonly name: string) {}
}
class Foo {
constructor(protected readonly name: string) {}
}
```
#### ✅ Correct
```ts
class Foo {
constructor(name: string) {}
}
class Foo {
constructor(public readonly name: string) {}
}
```
## When Not To Use It
If you don't care about the using parameter properties in constructors, then you will not need this rule.

View File

@@ -0,0 +1,73 @@
---
description: 'Disallow variable redeclaration.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-redeclare** for documentation.
## 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.
## Options
This rule adds the following options:
```ts
interface Options extends BaseNoRedeclareOptions {
ignoreDeclarationMerge?: boolean;
}
const defaultOptions: Options = {
...baseNoRedeclareDefaultOptions,
ignoreDeclarationMerge: true,
};
```
### `ignoreDeclarationMerge`
When set to `true`, the rule will ignore declaration merges between the following sets:
- interface + interface
- namespace + namespace
- class + interface
- class + namespace
- class + interface + namespace
- function + namespace
- enum + namespace
Examples of **correct** code with `{ ignoreDeclarationMerge: true }`:
```ts
interface A {
prop1: 1;
}
interface A {
prop2: 2;
}
namespace Foo {
export const a = 1;
}
namespace Foo {
export const b = 2;
}
class Bar {}
namespace Bar {}
function Baz() {}
namespace Baz {}
```
**Note:** Even with this option set to true, this rule will report if you name a type and a variable the same name. **_This is intentional_**.
Declaring a variable and a type and a variable the same is usually an accident, and it can lead to hard-to-understand code.
If you have a rare case where you're intentionally naming a type the same name as a variable, use a disable comment. For example:
```ts
type something = string;
// eslint-disable-next-line @typescript-eslint/no-redeclare -- intentionally naming the variable the same as the type
const something = 2;
```

View File

@@ -0,0 +1,78 @@
---
description: 'Disallow members of unions and intersections that do nothing or override type information.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-redundant-type-constituents** for documentation.
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.
Within `|` unions:
- `any` and `unknown` "override" all other union members
- `never` is dropped from unions in any position except when in a return type position
- primitive types such as `string` "override" any of their literal types such as `""`
Within `&` intersections:
- `any` and `never` "override" all other intersection members
- `unknown` is dropped from intersections
- literal types "override" any primitive types in an intersection
- literal types such as `""` "override" any of their primitive types such as `string`
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
type UnionAny = any | 'foo';
type UnionUnknown = unknown | 'foo';
type UnionNever = never | 'foo';
type UnionBooleanLiteral = boolean | false;
type UnionNumberLiteral = number | 1;
type UnionStringLiteral = string | 'foo';
type IntersectionAny = any & 'foo';
type IntersectionUnknown = string & unknown;
type IntersectionNever = string | never;
type IntersectionBooleanLiteral = boolean & false;
type IntersectionNumberLiteral = number & 1;
type IntersectionStringLiteral = string & 'foo';
```
### ✅ Correct
```ts
type UnionAny = any;
type UnionUnknown = unknown;
type UnionNever = never;
type UnionBooleanLiteral = boolean;
type UnionNumberLiteral = number;
type UnionStringLiteral = string;
type IntersectionAny = any;
type IntersectionUnknown = string;
type IntersectionNever = string;
type IntersectionBooleanLiteral = false;
type IntersectionNumberLiteral = 1;
type IntersectionStringLiteral = 'foo';
```
## Limitations
This rule plays it safe and only works with bottom types, top types, and comparing literal types to primitive types.
## Further Reading
- [Union Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types)
- [Intersection Types](https://www.typescriptlang.org/docs/handbook/2/objects.html#intersection-types)
- [Bottom Types](https://en.wikipedia.org/wiki/Bottom_type)
- [Top Types](https://en.wikipedia.org/wiki/Top_type)

View File

@@ -0,0 +1,37 @@
---
description: 'Disallow invocation of `require()`.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-require-imports** for documentation.
Prefer the newer ES6-style imports over `require()`.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
const lib1 = require('lib1');
const { lib2 } = require('lib2');
import lib3 = require('lib3');
```
### ✅ Correct
```ts
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 using newer module syntax, then you will not need this rule.
## Related To
- [`no-var-requires`](./no-var-requires.md)

View File

@@ -0,0 +1,63 @@
---
description: 'Disallow specified modules when loaded by `import`.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-restricted-imports** for documentation.
## Examples
This rule extends the base [`eslint/no-restricted-imports`](https://eslint.org/docs/rules/no-restricted-imports) rule.
## Options
This rule adds the following options:
### `allowTypeImports`
(default: `false`)
You can specify this option for a specific path or pattern as follows:
```jsonc
"@typescript-eslint/no-restricted-imports": ["error", {
"paths": [{
"name": "import-foo",
"message": "Please use import-bar instead.",
"allowTypeImports": true
}, {
"name": "import-baz",
"message": "Please use import-quux instead.",
"allowTypeImports": true
}]
}]
```
When set to `true`, the rule will allow [Type-Only Imports](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export).
Examples of code with the above config:
<!--tabs-->
#### ❌ Incorrect
```ts
import foo from 'import-foo';
export { Foo } from 'import-foo';
import baz from 'import-baz';
export { Baz } from 'import-baz';
```
#### ✅ Correct
```ts
import { foo } from 'other-module';
import type foo from 'import-foo';
export type { Foo } from 'import-foo';
import type baz from 'import-baz';
export type { Baz } from 'import-baz';
```

View File

@@ -0,0 +1,101 @@
---
description: 'Disallow variable declarations from shadowing variables declared in the outer scope.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-shadow** for documentation.
## 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.
## Options
This rule adds the following options:
```ts
interface Options extends BaseNoShadowOptions {
ignoreTypeValueShadow?: boolean;
ignoreFunctionTypeParameterNameValueShadow?: boolean;
}
const defaultOptions: Options = {
...baseNoShadowDefaultOptions,
ignoreTypeValueShadow: true,
ignoreFunctionTypeParameterNameValueShadow: true,
};
```
### `ignoreTypeValueShadow`
When set to `true`, the rule will ignore the case when you name a type the same as a variable.
TypeScript allows types and variables to shadow one-another. This is generally safe because you cannot use variables in type locations without a `typeof` operator, so there's little risk of confusion.
Examples of **correct** code with `{ ignoreTypeValueShadow: true }`:
```ts
type Foo = number;
const Foo = 1;
interface Bar {
prop: number;
}
const Bar = 'test';
```
### `ignoreFunctionTypeParameterNameValueShadow`
When set to `true`, the rule will ignore the case when you name a function type argument the same as a variable.
Each of a function type's arguments creates a value variable within the scope of the function type. This is done so that you can reference the type later using the `typeof` operator:
```ts
type Func = (test: string) => typeof test;
declare const fn: Func;
const result = fn('str'); // typeof result === string
```
This means that function type arguments shadow value variable names in parent scopes:
```ts
let test = 1;
type TestType = typeof test; // === number
type Func = (test: string) => typeof test; // this "test" references the argument, not the variable
declare const fn: Func;
const result = fn('str'); // typeof result === string
```
If you do not use the `typeof` operator in a function type return type position, you can safely turn this option on.
Examples of **correct** code with `{ ignoreFunctionTypeParameterNameValueShadow: true }`:
```ts
const test = 1;
type Func = (test: string) => typeof test;
```
## FAQ
### Why does the rule report on enum members that share the same name as a variable in a parent scope?
Reporting on this case isn't a bug - it is completely intentional and correct reporting! The rule reports due to a relatively unknown feature of enums - enum members create a variable within the enum scope so that they can be referenced within the enum without a qualifier.
To illustrate this with an example:
```ts
const A = 2;
enum Test {
A = 1,
B = A,
}
console.log(Test.B);
// what should be logged?
```
Naively looking at the above code, it might look like the log should output `2`, because the outer variable `A`'s value is `2` - however, the code instead outputs `1`, which is the value of `Test.A`. This is because the unqualified code `B = A` is equivalent to the fully-qualified code `B = Test.A`. Due to this behavior, the enum member has **shadowed** the outer variable declaration.

View File

@@ -0,0 +1,38 @@
---
description: 'Disallow aliasing `this`.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-this-alias** for documentation.
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
<!--tabs-->
### ❌ Incorrect
```js
const self = this;
setTimeout(function () {
self.doWork();
});
```
### ✅ Correct
```js
setTimeout(() => {
this.doWork();
});
```
## Options
## When Not To Use It
If you need to assign `this` to variables, you shouldnt use this rule.

View File

@@ -0,0 +1,111 @@
---
description: 'Disallow throwing literals as exceptions.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-throw-literal** for documentation.
It is considered good practice to only `throw` the `Error` object itself or an object using the `Error` object as base objects for user-defined exceptions.
The fundamental benefit of `Error` objects is that they automatically keep track of where they were built and originated.
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`.
## 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.
<!--tabs-->
### ❌ Incorrect
```ts
/*eslint @typescript-eslint/no-throw-literal: "error"*/
throw 'error';
throw 0;
throw undefined;
throw null;
const err = new Error();
throw 'an ' + err;
const err = new Error();
throw `${err}`;
const err = '';
throw err;
function err() {
return '';
}
throw err();
const foo = {
bar: '',
};
throw foo.bar;
```
### ✅ Correct
```ts
/*eslint @typescript-eslint/no-throw-literal: "error"*/
throw new Error();
throw new Error("error");
const e = new Error("error");
throw e;
try {
throw new Error("error");
} catch (e) {
throw e;
}
const err = new Error();
throw err;
function err() {
return new Error();
}
throw err();
const foo = {
bar: new Error();
}
throw foo.bar;
class CustomError extends Error {
// ...
};
throw new CustomError();
```
## Options
This rule adds the following options:
```ts
interface Options {
/**
* Whether to always allow throwing values typed as `any`.
*/
allowThrowingAny?: boolean;
/**
* Whether to always allow throwing values typed as `unknown`.
*/
allowThrowingUnknown?: boolean;
}
const defaultOptions: Options = {
allowThrowingAny: false,
allowThrowingUnknown: false,
};
```

View File

@@ -0,0 +1,602 @@
---
description: 'Disallow type aliases.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-type-alias** for documentation.
In TypeScript, type aliases serve three purposes:
- Aliasing other types so that we can refer to them using a simpler name.
```ts
// this...
type Person = {
firstName: string,
lastName: string,
age: number
};
function addPerson(person : Person) { ... }
// is easier to read than this...
function addPerson(person : { firstName: string, lastName: string, age: number}) { ... }
```
- Act sort of like an interface, providing a set of methods and properties that must exist
in the objects implementing the type.
```ts
type Person = {
firstName: string,
lastName: string,
age: number,
walk: () => void,
talk: () => void
};
// you know person will have 3 properties and 2 methods,
// because the structure has already been defined.
var person : Person = { ... }
// so we can be sure that this will work
person.walk();
```
- Act like mapping tools between types to allow quick modifications.
```ts
type Immutable<T> = { readonly [P in keyof T]: T[P] };
type Person = {
name: string;
age: number;
};
type ImmutablePerson = Immutable<Person>;
var person: ImmutablePerson = { name: 'John', age: 30 };
person.name = 'Brad'; // error, readonly property
```
When aliasing, the type alias does not create a new type, it just creates a new name
to refer to the original type. So aliasing primitives and other simple types, tuples, unions
or intersections can some times be redundant.
```ts
// this doesn't make much sense
type myString = string;
```
On the other hand, using a type alias as an interface can limit your ability to:
- Reuse your code: interfaces can be extended or implemented by other types. Type aliases cannot.
- Debug your code: interfaces create a new name, so is easy to identify the base type of an object
while debugging the application.
Finally, mapping types is an advanced technique and leaving it open can quickly become a pain point
in your application.
## Examples
This rule disallows the use of type aliases in favor of interfaces
and simplified types (primitives, tuples, unions, intersections, etc).
## Options
### `allowAliases`
This applies to primitive types and reference types.
The setting accepts the following values:
- `"always"` or `"never"` to active or deactivate the feature.
- `"in-unions"`, allows aliasing in union statements, e.g. `type Foo = string | string[];`
- `"in-intersections"`, allows aliasing in intersection statements, e.g. `type Foo = string & string[];`
- `"in-unions-and-intersections"`, allows aliasing in union and/or intersection statements.
Examples of **correct** code for the `{ "allowAliases": "always" }` options:
```ts
// primitives
type Foo = 'a';
type Foo = 'a' | 'b';
type Foo = string;
type Foo = string | string[];
type Foo = string & string[];
type Foo = `foo-${number}`;
// reference types
interface Bar {}
class Baz implements Bar {}
type Foo = Bar;
type Foo = Bar | Baz;
type Foo = Bar & Baz;
```
Examples of **incorrect** code for the `{ "allowAliases": "in-unions" }` option:
```ts
// primitives
type Foo = 'a';
type Foo = string;
type Foo = string & string[];
type Foo = `foo-${number}`;
// reference types
interface Bar {}
class Baz implements Bar {}
type Foo = Bar;
type Foo = Bar & Baz;
```
Examples of **correct** code for the `{ "allowAliases": "in-unions" }` option:
```ts
// primitives
type Foo = 'a' | 'b';
type Foo = string | string[];
type Foo = `a-${number}` | `b-${number}`;
// reference types
interface Bar {}
class Baz implements Bar {}
type Foo = Bar | Baz;
```
Examples of **incorrect** code for the `{ "allowAliases": "in-intersections" }` option:
```ts
// primitives
type Foo = 'a';
type Foo = 'a' | 'b';
type Foo = string;
type Foo = string | string[];
type Foo = `a-${number}` | `b-${number}`;
// reference types
interface Bar {}
class Baz implements Bar {}
type Foo = Bar;
type Foo = Bar | Baz;
```
Examples of **correct** code for the `{ "allowAliases": "in-intersections" }` option:
```ts
// primitives
type Foo = string & string[];
type Foo = `a-${number}` & `b-${number}`;
// reference types
interface Bar {}
class Baz implements Bar {}
type Foo = Bar & Baz;
```
Examples of **incorrect** code for the `{ "allowAliases": "in-unions-and-intersections" }` option:
```ts
// primitives
type Foo = 'a';
type Foo = string;
type Foo = `foo-${number}`;
// reference types
interface Bar {}
class Baz implements Bar {}
type Foo = Bar;
```
Examples of **correct** code for the `{ "allowAliases": "in-unions-and-intersections" }` option:
```ts
// primitives
type Foo = 'a' | 'b';
type Foo = string | string[];
type Foo = string & string[];
type Foo = `a-${number}` & `b-${number}`;
type Foo = `a-${number}` | `b-${number}`;
// reference types
interface Bar {}
class Baz implements Bar {}
type Foo = Bar | Baz;
type Foo = Bar & Baz;
```
### `allowCallbacks`
This applies to function types.
The setting accepts the following values:
- `"always"` or `"never"` to active or deactivate the feature.
Examples of **correct** code for the `{ "allowCallbacks": "always" }` option:
```ts
type Foo = () => void;
type Foo = (name: string) => string;
class Person {}
type Foo = (name: string, age: number) => string | Person;
type Foo = (name: string, age: number) => string & Person;
```
### `allowConditionalTypes`
This applies to conditional types.
Examples of **correct** code for the `{ "allowConditionalTypes": "always" }` option:
```ts
type Foo<T> = T extends number ? number : null;
```
### `allowConstructors`
This applies to constructor types.
The setting accepts the following values:
- `"always"` or `"never"` to active or deactivate the feature.
Examples of **correct** code for the `{ "allowConstructors": "always" }` option:
```ts
type Foo = new () => void;
```
### `allowLiterals`
This applies to literal types (`type Foo = { ... }`).
The setting accepts the following options:
- `"always"` or `"never"` to active or deactivate the feature.
- `"in-unions"`, allows literals in union statements, e.g. `type Foo = string | string[];`
- `"in-intersections"`, allows literals in intersection statements, e.g. `type Foo = string & string[];`
- `"in-unions-and-intersections"`, allows literals in union and/or intersection statements.
Examples of **correct** code for the `{ "allowLiterals": "always" }` options:
```ts
type Foo = {};
type Foo = {
name: string;
age: number;
};
type Foo = {
name: string;
age: number;
walk: (miles: number) => void;
};
type Foo = { name: string } | { age: number };
type Foo = { name: string } & { age: number };
```
Examples of **incorrect** code for the `{ "allowLiterals": "in-unions" }` option:
```ts
type Foo = {};
type Foo = {
name: string;
age: number;
};
type Foo = {
name: string;
age: number;
walk: (miles: number) => void;
};
type Foo = { name: string } & { age: number };
```
Examples of **correct** code for the `{ "allowLiterals": "in-unions" }` option:
```ts
type Foo = { name: string } | { age: number };
```
Examples of **incorrect** code for the `{ "allowLiterals": "in-intersections" }` option:
```ts
type Foo = {};
type Foo = {
name: string;
age: number;
};
type Foo = {
name: string;
age: number;
walk: (miles: number) => void;
};
type Foo = { name: string } | { age: number };
```
Examples of **correct** code for the `{ "allowLiterals": "in-intersections" }` option:
```ts
type Foo = { name: string } & { age: number };
```
Examples of **incorrect** code for the `{ "allowLiterals": "in-unions-and-intersections" }` option:
```ts
type Foo = {};
type Foo = {
name: string;
age: number;
};
type Foo = {
name: string;
age: number;
walk: (miles: number) => void;
};
```
Examples of **correct** code for the `{ "allowLiterals": "in-unions-and-intersections" }` option:
```ts
type Foo = { name: string } | { age: number };
type Foo = { name: string } & { age: number };
```
### `allowMappedTypes`
This applies to literal types.
The setting accepts the following values:
- `"always"` or `"never"` to active or deactivate the feature.
- `"in-unions"`, allows aliasing in union statements, e.g. `type Foo = string | string[];`
- `"in-intersections"`, allows aliasing in intersection statements, e.g. `type Foo = string & string[];`
- `"in-unions-and-intersections"`, allows aliasing in union and/or intersection statements.
Examples of **correct** code for the `{ "allowMappedTypes": "always" }` options:
```ts
type Foo<T> = { readonly [P in keyof T]: T[P] };
type Foo<T> = { [P in keyof T]?: T[P] };
type Foo<T, U> =
| { readonly [P in keyof T]: T[P] }
| { readonly [P in keyof U]: U[P] };
type Foo<T, U> = { [P in keyof T]?: T[P] } | { [P in keyof U]?: U[P] };
type Foo<T, U> = { readonly [P in keyof T]: T[P] } & {
readonly [P in keyof U]: U[P];
};
type Foo<T, U> = { [P in keyof T]?: T[P] } & { [P in keyof U]?: U[P] };
```
Examples of **incorrect** code for the `{ "allowMappedTypes": "in-unions" }` option:
```ts
type Foo<T> = { readonly [P in keyof T]: T[P] };
type Foo<T> = { [P in keyof T]?: T[P] };
type Foo<T, U> = { readonly [P in keyof T]: T[P] } & {
readonly [P in keyof U]: U[P];
};
type Foo<T, U> = { [P in keyof T]?: T[P] } & { [P in keyof U]?: U[P] };
```
Examples of **correct** code for the `{ "allowMappedTypes": "in-unions" }` option:
```ts
type Foo<T, U> =
| { readonly [P in keyof T]: T[P] }
| { readonly [P in keyof U]: U[P] };
type Foo<T, U> = { [P in keyof T]?: T[P] } | { [P in keyof U]?: U[P] };
```
Examples of **incorrect** code for the `{ "allowMappedTypes": "in-intersections" }` option:
```ts
type Foo<T> = { readonly [P in keyof T]: T[P] };
type Foo<T> = { [P in keyof T]?: T[P] };
type Foo<T, U> =
| { readonly [P in keyof T]: T[P] }
| { readonly [P in keyof U]: U[P] };
type Foo<T, U> = { [P in keyof T]?: T[P] } | { [P in keyof U]?: U[P] };
```
Examples of **correct** code for the `{ "allowMappedTypes": "in-intersections" }` option:
```ts
type Foo<T, U> = { readonly [P in keyof T]: T[P] } & {
readonly [P in keyof U]: U[P];
};
type Foo<T, U> = { [P in keyof T]?: T[P] } & { [P in keyof U]?: U[P] };
```
Examples of **incorrect** code for the `{ "allowMappedTypes": "in-unions-and-intersections" }` option:
```ts
type Foo<T> = { readonly [P in keyof T]: T[P] };
type Foo<T> = { [P in keyof T]?: T[P] };
```
Examples of **correct** code for the `{ "allowMappedTypes": "in-unions-and-intersections" }` option:
```ts
type Foo<T, U> =
| { readonly [P in keyof T]: T[P] }
| { readonly [P in keyof U]: U[P] };
type Foo<T, U> = { [P in keyof T]?: T[P] } | { [P in keyof U]?: U[P] };
type Foo<T, U> = { readonly [P in keyof T]: T[P] } & {
readonly [P in keyof U]: U[P];
};
type Foo<T, U> = { [P in keyof T]?: T[P] } & { [P in keyof U]?: U[P] };
```
### `allowTupleTypes`
This applies to tuple types (`type Foo = [number]`).
The setting accepts the following options:
- `"always"` or `"never"` to active or deactivate the feature.
- `"in-unions"`, allows tuples in union statements, e.g. `type Foo = [string] | [string, string];`
- `"in-intersections"`, allows tuples in intersection statements, e.g. `type Foo = [string] & [string, string];`
- `"in-unions-and-intersections"`, allows tuples in union and/or intersection statements.
Examples of **correct** code for the `{ "allowTupleTypes": "always" }` options:
```ts
type Foo = [number];
type Foo = [number] | [number, number];
type Foo = [number] & [number, number];
type Foo = [number] | ([number, number] & [string, string]);
```
Examples of **incorrect** code for the `{ "allowTupleTypes": "in-unions" }` option:
```ts
type Foo = [number];
type Foo = [number] & [number, number];
type Foo = [string] & [number];
```
Examples of **correct** code for the `{ "allowTupleTypes": "in-unions" }` option:
```ts
type Foo = [number] | [number, number];
type Foo = [string] | [number];
```
Examples of **incorrect** code for the `{ "allowTupleTypes": "in-intersections" }` option:
```ts
type Foo = [number];
type Foo = [number] | [number, number];
type Foo = [string] | [number];
```
Examples of **correct** code for the `{ "allowTupleTypes": "in-intersections" }` option:
```ts
type Foo = [number] & [number, number];
type Foo = [string] & [number];
```
Examples of **incorrect** code for the `{ "allowTupleTypes": "in-unions-and-intersections" }` option:
```ts
type Foo = [number];
type Foo = [string];
```
Examples of **correct** code for the `{ "allowLiterals": "in-unions-and-intersections" }` option:
```ts
type Foo = [number] & [number, number];
type Foo = [string] | [number];
```
### `allowGenerics`
This applies to generic types, including TypeScript provided global utility types (`type Foo = Record<string, number>`).
The setting accepts the following options:
- `"always"` or `"never"` to active or deactivate the feature.
Examples of **correct** code for the `{ "allowGenerics": "always" }` options:
```ts
type Foo = Bar<string>;
type Foo = Record<string, number>;
type Foo = Readonly<Bar>;
type Foo = Partial<Bar>;
type Foo = Omit<Bar, 'a' | 'b'>;
```
## When Not To Use It
When you can't express some shape with an interface or you need to use a union, tuple type,
callback, etc. that would cause the code to be unreadable or impractical.
## Further Reading
- [Advanced Types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)

View File

@@ -0,0 +1,133 @@
---
description: 'Disallow unnecessary equality comparisons against boolean literals.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> 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.
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`, etc.).
## 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 `!==` would be treated the same way if `!=` was used.
:::
<!--tabs-->
### ❌ Incorrect
```ts
declare const someCondition: boolean;
if (someCondition === true) {
}
```
### ✅ Correct
```ts
declare const someCondition: boolean;
if (someCondition) {
}
declare const someObjectBoolean: boolean | Record<string, unknown>;
if (someObjectBoolean === true) {
}
declare const someStringBoolean: boolean | string;
if (someStringBoolean === true) {
}
```
## Options
This rule always checks comparisons between a boolean variable and a boolean
literal. Comparisons between nullable boolean variables and boolean literals
are **not** checked by default.
### `allowComparingNullableBooleansToTrue`
Examples of code for this rule with `{ allowComparingNullableBooleansToTrue: false }`:
<!--tabs-->
#### ❌ Incorrect
```ts
declare const someUndefinedCondition: boolean | undefined;
if (someUndefinedCondition === true) {
}
declare const someNullCondition: boolean | null;
if (someNullCondition !== true) {
}
```
#### ✅ Correct
```ts
declare const someUndefinedCondition: boolean | undefined;
if (someUndefinedCondition) {
}
declare const someNullCondition: boolean | null;
if (!someNullCondition) {
}
```
### `allowComparingNullableBooleansToFalse`
Examples of code for this rule with `{ allowComparingNullableBooleansToFalse: false }`:
<!--tabs-->
#### ❌ Incorrect
```ts
declare const someUndefinedCondition: boolean | undefined;
if (someUndefinedCondition === false) {
}
declare const someNullCondition: boolean | null;
if (someNullCondition !== false) {
}
```
#### ✅ Correct
```ts
declare const someUndefinedCondition: boolean | undefined;
if (someUndefinedCondition ?? true) {
}
declare const someNullCondition: boolean | null;
if (!(someNullCondition ?? true)) {
}
```
## Fixer
| Comparison | Fixer Output | Notes |
| :-------------------------------: | ------------------------------- | ----------------------------------------------------------------------------------- |
| `booleanVar === true` | `booleanVar` | |
| `booleanVar !== true` | `!booleanVar` | |
| `booleanVar === false` | `!booleanVar` | |
| `booleanVar !== false` | `booleanVar` | |
| `nullableBooleanVar === true` | `nullableBooleanVar` | Only checked/fixed if the `allowComparingNullableBooleansToTrue` option is `false` |
| `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.

View File

@@ -0,0 +1,103 @@
---
description: 'Disallow conditionals where the type is always truthy or always falsy.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> 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.
The following expressions are checked:
- Arguments to the `&&`, `||` and `?:` (ternary) operators
- Conditions for `if`, `for`, `while`, and `do-while` statements
- Base values of optional chain expressions
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
function head<T>(items: T[]) {
// items can never be nullable, so this is unnecessary
if (items) {
return items[0].toUpperCase();
}
}
function foo(arg: 'bar' | 'baz') {
// arg is never nullable or empty string, so this is unnecessary
if (arg) {
}
}
function bar<T>(arg: string) {
// arg can never be nullish, so ?. is unnecessary
return arg?.length;
}
// Checks array predicate return types, where possible
[
[1, 2],
[3, 4],
].filter(t => t); // number[] is always truthy
```
### ✅ Correct
```ts
function head<T>(items: T[]) {
// Necessary, since items.length might be 0
if (items.length) {
return items[0].toUpperCase();
}
}
function foo(arg: string) {
// Necessary, since foo might be ''.
if (arg) {
}
}
function bar(arg?: string | null) {
// Necessary, since arg might be nullish
return arg?.length;
}
[0, 1, 2, 3].filter(t => t); // number can be truthy or falsy
```
## Options
### `allowConstantLoopConditions`
Example of correct code for `{ allowConstantLoopConditions: true }`:
```ts
while (true) {}
for (; true; ) {}
do {} while (true);
```
### `allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing`
If this is set to `false`, then the rule will error on every file whose `tsconfig.json` does _not_ have the `strictNullChecks` compiler option (or `strict`) set to `true`.
Without `strictNullChecks`, TypeScript essentially erases `undefined` and `null` from the types. This means when this rule inspects the types from a variable, **it will not be able to tell that the variable might be `null` or `undefined`**, which essentially makes this rule useless.
You should be using `strictNullChecks` to ensure complete type-safety in your codebase.
If for some reason you cannot turn on `strictNullChecks`, but still want to use this rule - you can use this option to allow it - but know that the behavior of this rule is _undefined_ with the compiler option turned off. We will not accept bug reports if you are using this option.
## When Not To Use It
The main downside to using this rule is the need for type information.
## Related To
- ESLint: [no-constant-condition](https://eslint.org/docs/rules/no-constant-condition) - `no-unnecessary-condition` is essentially a stronger version of `no-constant-condition`, but requires type information.
- [strict-boolean-expressions](./strict-boolean-expressions.md) - a more opinionated version of `no-unnecessary-condition`. `strict-boolean-expressions` enforces a specific code style, while `no-unnecessary-condition` is about correctness.

View File

@@ -0,0 +1,51 @@
---
description: 'Disallow unnecessary namespace qualifiers.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-unnecessary-qualifier** for documentation.
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.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
enum A {
B,
C = A.B,
}
```
```ts
namespace A {
export type B = number;
const x: A.B = 3;
}
```
### ✅ Correct
```ts
enum A {
B,
C = B,
}
```
```ts
namespace A {
export type B = number;
const x: B = 3;
}
```
## When Not To Use It
If you don't care about having unneeded enum or namespace qualifiers, then you don't need to use this rule.

View File

@@ -0,0 +1,73 @@
---
description: 'Disallow type arguments that are equal to the default.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-unnecessary-type-arguments** for documentation.
Type parameters in TypeScript may specify a default value.
For example:
```ts
function f<T = number>(...) {...}
```
It is redundant to provide an explicit type parameter equal to that default: e.g. calling `f<number>(...)`.
This rule reports when an explicitly specified type argument is the default for that type parameter.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
function f<T = number>() {}
f<number>();
```
```ts
function g<T = number, U = string>() {}
g<string, string>();
```
```ts
class C<T = number> {}
new C<number>();
class D extends C<number> {}
```
```ts
interface I<T = number> {}
class Impl implements I<number> {}
```
### ✅ Correct
```ts
function f<T = number>() {}
f();
f<string>();
```
```ts
function g<T = number, U = string>() {}
g<string>();
g<number, number>();
```
```ts
class C<T = number> {}
new C();
new C<string>();
class D extends C {}
class D extends C<string> {}
```
```ts
interface I<T = number> {}
class Impl implements I<string> {}
```

View File

@@ -0,0 +1,77 @@
---
description: 'Disallow type assertions that do not change the type of an expression.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-unnecessary-type-assertion** for documentation.
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
<!--tabs-->
### ❌ Incorrect
```ts
const foo = 3;
const bar = foo!;
```
```ts
const foo = <3>3;
```
```ts
type Foo = 3;
const foo = <Foo>3;
```
```ts
type Foo = 3;
const foo = 3 as Foo;
```
```ts
function foo(x: number): number {
return x!; // unnecessary non-null
}
```
### ✅ Correct
```ts
const foo = <number>3;
```
```ts
const foo = 3 as number;
```
```ts
const foo = 'foo' as const;
```
```ts
function foo(x: number | undefined): number {
return x!;
}
```
## Options
### `typesToIgnore`
With `@typescript-eslint/no-unnecessary-type-assertion: ["error", { typesToIgnore: ['Foo'] }]`, the following is **correct** code":
```ts
type Foo = 3;
const foo: Foo = 3;
```
## When Not To Use It
If you don't care about having no-op type assertions in your code, then you can turn off this rule.

View File

@@ -0,0 +1,55 @@
---
description: 'Disallow unnecessary constraints on generic types.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-unnecessary-type-constraint** for documentation.
Generic type parameters (`<T>`) 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 `unknown`.
It is therefore redundant to `extend` from `any` or `unknown`.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
interface FooAny<T extends any> {}
interface FooUnknown<T extends unknown> {}
type BarAny<T extends any> = {};
type BarUnknown<T extends unknown> = {};
class BazAny<T extends any> {
quxAny<U extends any>() {}
}
const QuuxAny = <T extends any>() => {};
function QuuzAny<T extends any>() {}
```
### ✅ Correct
```ts
interface Foo<T> {}
type Bar<T> = {};
class Baz<T> {
qux<U> { }
}
const Quux = <T>() => {};
function Quuz<T>() {}
```
## When Not To Use It
If you don't care about the specific styles of your type constraints, or never use them in the first place, then you will not need this rule.

View File

@@ -0,0 +1,83 @@
---
description: 'Disallow calling a function with a value with type `any`.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> 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.
Calling a function with an `any` typed argument creates a potential safety hole and source of bugs.
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 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<any>` as an argument to a parameter declared as `Set<string>`.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
declare function foo(arg1: string, arg2: number, arg3: string): void;
const anyTyped = 1 as any;
foo(...anyTyped);
foo(anyTyped, 1, 'a');
const anyArray: any[] = [];
foo(...anyArray);
const tuple1 = ['a', anyTyped, 'b'] as const;
foo(...tuple1);
const tuple2 = [1] as const;
foo('a', ...tuple, anyTyped);
declare function bar(arg1: string, arg2: number, ...rest: string[]): void;
const x = [1, 2] as [number, ...number[]];
foo('a', ...x, anyTyped);
declare function baz(arg1: Set<string>, arg2: Map<string, string>): void;
foo(new Set<any>(), new Map<any, string>());
```
### ✅ Correct
```ts
declare function foo(arg1: string, arg2: number, arg3: string): void;
foo('a', 1, 'b');
const tuple1 = ['a', 1, 'b'] as const;
foo(...tuple1);
declare function bar(arg1: string, arg2: number, ...rest: string[]): void;
const array: string[] = ['a'];
bar('a', 1, ...array);
declare function baz(arg1: Set<string>, arg2: Map<string, string>): void;
foo(new Set<string>(), new Map<string, string>());
```
<!--/tabs-->
There are cases where the rule allows passing an argument of `any` to `unknown`.
Example of `any` to `unknown` assignment that are allowed:
```ts
declare function foo(arg1: unknown, arg2: Set<unkown>, arg3: unknown[]): void;
foo(1 as any, new Set<any>(), [] as any[]);
```
## Related To
- [`no-explicit-any`](./no-explicit-any.md)

View File

@@ -0,0 +1,86 @@
---
description: 'Disallow assigning a value with type `any` to variables and properties.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-unsafe-assignment** 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.
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 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<any>` to a variable declared as `Set<string>`.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
const x = 1 as any,
y = 1 as any;
const [x] = 1 as any;
const [x] = [] as any[];
const [x] = [1 as any];
[x] = [1] as [any];
function foo(a = 1 as any) {}
class Foo {
constructor(private a = 1 as any) {}
}
class Foo {
private a = 1 as any;
}
// generic position examples
const x: Set<string> = new Set<any>();
const x: Map<string, string> = new Map<string, any>();
const x: Set<string[]> = new Set<any[]>();
const x: Set<Set<Set<string>>> = new Set<Set<Set<any>>>();
```
### ✅ Correct
```ts
const x = 1,
y = 1;
const [x] = [1];
[x] = [1] as [number];
function foo(a = 1) {}
class Foo {
constructor(private a = 1) {}
}
class Foo {
private a = 1;
}
// generic position examples
const x: Set<string> = new Set<string>();
const x: Map<string, string> = new Map<string, string>();
const x: Set<string[]> = new Set<string[]>();
const x: Set<Set<Set<string>>> = new Set<Set<Set<string>>>();
```
<!--/tabs-->
There are cases where the rule allows assignment of `any` to `unknown`.
Example of `any` to `unknown` assignment that are allowed:
```ts
const x: unknown = y as any;
const x: unknown[] = y as any[];
const x: Set<unknown> = y as Set<any>;
```
## Related To
- [`no-explicit-any`](./no-explicit-any.md)

View File

@@ -0,0 +1,58 @@
---
description: 'Disallow calling a value with type `any`.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> 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.
Calling an `any`-typed value as a function creates a potential type safety hole and source of bugs in your codebase.
This rule disallows calling any value that is typed as `any`.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
declare const anyVar: any;
declare const nestedAny: { prop: any };
anyVar();
anyVar.a.b();
nestedAny.prop();
nestedAny.prop['a']();
new anyVar();
new nestedAny.prop();
anyVar`foo`;
nestedAny.prop`foo`;
```
### ✅ Correct
```ts
declare const typedVar: () => void;
declare const typedNested: { prop: { a: () => void } };
typedVar();
typedNested.prop.a();
(() => {})();
new Map();
String.raw`foo`;
```
## Related To
- [`no-explicit-any`](./no-explicit-any.md)

View File

@@ -0,0 +1,54 @@
---
description: 'Disallow unsafe declaration merging.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-unsafe-declaration-merging** for documentation.
TypeScript's "declaration merging" supports merging separate declarations with the same name.
Declaration merging between classes and interfaces is unsafe.
The TypeScript compiler doesn't check whether properties are initialized, which can cause lead to TypeScript not detecting code that will cause runtime errors.
```ts
interface Foo {
nums: number[];
}
class Foo {}
const foo = new Foo();
foo.nums.push(1); // Runtime Error: Cannot read properties of undefined.
```
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
interface Foo {}
class Foo {}
```
### ✅ Correct
```ts
interface Foo {}
class Bar implements Foo {}
namespace Baz {}
namespace Baz {}
enum Baz {}
namespace Qux {}
function Qux() {}
```
## Further Reading
- [Declaration Merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html)

View File

@@ -0,0 +1,75 @@
---
description: 'Disallow comparing an enum value with a non-enum value.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-unsafe-enum-comparison** for documentation.
The TypeScript compiler can be surprisingly lenient when working with enums.
For example, it will allow you to compare enum values against numbers even though they might not have any type overlap:
```ts
enum Fruit {
Apple,
Banana,
}
declare let fruit: Fruit;
fruit === 999; // No error
```
This rule flags when an enum typed value is compared to a non-enum `number`.
<!--tabs-->
### ❌ Incorrect
```ts
enum Fruit {
Apple,
}
declare let fruit: Fruit;
fruit === 999;
```
```ts
enum Vegetable {
Asparagus = 'asparagus',
}
declare let vegetable: Vegetable;
vegetable === 'asparagus';
```
### ✅ Correct
```ts
enum Fruit {
Apple,
}
declare let fruit: Fruit;
fruit === Fruit.Banana;
```
```ts
enum Vegetable {
Asparagus = 'asparagus',
}
declare let vegetable: Vegetable;
vegetable === Vegetable.Asparagus;
```
<!--/tabs-->
## When Not to Use It
If you don't mind number and/or literal string constants being compared against enums, you likely don't need this rule.

View File

@@ -0,0 +1,64 @@
---
description: 'Disallow member access on a value with type `any`.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-unsafe-member-access** 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.
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
<!--tabs-->
### ❌ Incorrect
```ts
declare const anyVar: any;
declare const nestedAny: { prop: any };
anyVar.a;
anyVar.a.b;
anyVar['a'];
anyVar['a']['b'];
nestedAny.prop.a;
nestedAny.prop['a'];
const key = 'a';
nestedAny.prop[key];
// Using an any to access a member is unsafe
const arr = [1, 2, 3];
arr[anyVar];
nestedAny[anyVar];
```
### ✅ Correct
```ts
declare const properlyTyped: { prop: { a: string } };
properlyTyped.prop.a;
properlyTyped.prop['a'];
const key = 'a';
properlyTyped.prop[key];
const arr = [1, 2, 3];
arr[1];
const idx = 1;
arr[idx];
arr[idx++];
```
## Related To
- [`no-explicit-any`](./no-explicit-any.md)

View File

@@ -0,0 +1,103 @@
---
description: 'Disallow returning a value with type `any` from a function.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-unsafe-return** 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.
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 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<any>` from a function declared as returning `Set<string>`.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
function foo1() {
return 1 as any;
}
function foo2() {
return Object.create(null);
}
const foo3 = () => {
return 1 as any;
};
const foo4 = () => Object.create(null);
function foo5() {
return [] as any[];
}
function foo6() {
return [] as Array<any>;
}
function foo7() {
return [] as readonly any[];
}
function foo8() {
return [] as Readonly<any[]>;
}
const foo9 = () => {
return [] as any[];
};
const foo10 = () => [] as any[];
const foo11 = (): string[] => [1, 2, 3] as any[];
// generic position examples
function assignability1(): Set<string> {
return new Set<any>([1]);
}
type TAssign = () => Set<string>;
const assignability2: TAssign = () => new Set<any>([true]);
```
### ✅ Correct
```ts
function foo1() {
return 1;
}
function foo2() {
return Object.create(null) as Record<string, unknown>;
}
const foo3 = () => [];
const foo4 = () => ['a'];
function assignability1(): Set<string> {
return new Set<string>(['foo']);
}
type TAssign = () => Set<string>;
const assignability2: TAssign = () => new Set(['foo']);
```
<!--/tabs-->
There are cases where the rule allows to return `any` to `unknown`.
Examples of `any` to `unknown` return that are allowed:
```ts
function foo1(): unknown {
return JSON.parse(singleObjString); // Return type for JSON.parse is any.
}
function foo2(): unknown[] {
return [] as any[];
}
```
## Related To
- [`no-explicit-any`](./no-explicit-any.md)

View File

@@ -0,0 +1,12 @@
---
description: 'Disallow unused expressions.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-unused-expressions** for documentation.
## 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.

View File

@@ -0,0 +1,12 @@
---
description: 'Disallow unused variables.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-unused-vars** for documentation.
## 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.

View File

@@ -0,0 +1,97 @@
---
description: 'Disallow the use of variables before they are defined.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-use-before-define** for documentation.
## 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.
## Options
This rule adds the following options:
```ts
interface Options extends BaseNoUseBeforeDefineOptions {
enums?: boolean;
typedefs?: boolean;
ignoreTypeReferences?: boolean;
}
const defaultOptions: Options = {
...baseNoUseBeforeDefineDefaultOptions,
enums: true,
typedefs: true,
ignoreTypeReferences: true,
};
```
### `enums`
If this is `true`, this rule warns every reference to a enum before the enum declaration.
If this is `false`, this rule will ignore references to enums, when the reference is in a child scope.
Examples of code for the `{ "enums": true }` option:
<!--tabs-->
#### ❌ Incorrect
```ts
/*eslint no-use-before-define: ["error", { "enums": true }]*/
const x = Foo.FOO;
enum Foo {
FOO,
}
```
#### ✅ Correct
```ts
/*eslint no-use-before-define: ["error", { "enums": false }]*/
function foo() {
return Foo.FOO;
}
enum Foo {
FOO,
}
```
### `typedefs`
If this is `true`, this rule warns every reference to a type before the type declaration.
If this is `false`, this rule will ignore references to types.
Examples of **correct** code for the `{ "typedefs": false }` option:
```ts
/*eslint no-use-before-define: ["error", { "typedefs": false }]*/
let myVar: StringOrNumber;
type StringOrNumber = string | number;
```
### `ignoreTypeReferences`
If this is `true`, this rule ignores all type references, such as in type annotations and assertions.
If this is `false`, this will will check all type references.
Examples of **correct** code for the `{ "ignoreTypeReferences": true }` option:
```ts
/*eslint no-use-before-define: ["error", { "ignoreTypeReferences": true }]*/
let var1: StringOrNumber;
type StringOrNumber = string | number;
let var2: Enum;
enum Enum {}
```

View File

@@ -0,0 +1,21 @@
---
description: 'Disallow unnecessary constructors.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-useless-constructor** for documentation.
## Examples
This rule extends the base [`eslint/no-useless-constructor`](https://eslint.org/docs/rules/no-useless-constructor) rule.
It adds support for:
- constructors marked as `protected` / `private` (i.e. marking a constructor as non-public),
- `public` constructors when there is no superclass,
- constructors with only parameter properties.
### Caveat
This lint rule will report on constructors whose sole purpose is to change visibility of a parent constructor.
See [discussion on this rule's lack of type information](https://github.com/typescript-eslint/typescript-eslint/issues/3820#issuecomment-917821240) for context.

View File

@@ -0,0 +1,43 @@
---
description: "Disallow empty exports that don't change anything in a module file."
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-useless-empty-export** for documentation.
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 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
<!--tabs-->
### ❌ Incorrect
```ts
export const value = 'Hello, world!';
export {};
```
```ts
import 'some-other-module';
export {};
```
### ✅ Correct
```ts
export const value = 'Hello, world!';
```
```ts
import 'some-other-module';
```

View File

@@ -0,0 +1,37 @@
---
description: 'Disallow `require` statements except in import statements.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/no-var-requires** for documentation.
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.
## Examples
<!--tabs-->
### ❌ Incorrect
```ts
var foo = require('foo');
const foo = require('foo');
let foo = require('foo');
```
### ✅ Correct
```ts
import foo = require('foo');
require('foo');
import foo from 'foo';
```
## When Not To Use It
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)

View File

@@ -0,0 +1,41 @@
---
description: 'Enforce non-null assertions over explicit type casts.'
---
> 🛑 This file is source code, not the primary documentation location! 🛑
>
> See **https://typescript-eslint.io/rules/non-nullable-type-assertion-style** for documentation.
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
<!--tabs-->
### ❌ Incorrect
```ts
const maybe = Math.random() > 0.5 ? '' : undefined;
const definitely = maybe as string;
const alsoDefinitely = <string>maybe;
```
### ✅ Correct
```ts
const maybe = Math.random() > 0.5 ? '' : undefined;
const definitely = maybe!;
const alsoDefinitely = maybe!;
```
## When Not To Use It
If you don't mind having unnecessarily verbose type casts, you can avoid this rule.

Some files were not shown because too many files have changed in this diff Show More