# @typescript-eslint/no-magic-numbers

> Disallow numbers that are used without a name

A bare number in an expression doesn't say what it stands for. `price * 0.2` could be a tax, a discount or a tip. If you write the same number in three places, you have to find all three to change it. A named `const` fixes both.

The rule doesn't report the number a variable is declared with, a value in an object literal, a number assigned to a property, the radix of `parseInt()` or a number in JSX. It reports every other number, including `0` and `1`.

It's the TypeScript version of `no-magic-numbers` and takes the same options.

With `bunfig.toml` you can set either name. `bun lint` runs this rule in TypeScript files and `no-magic-numbers` in JavaScript files, so nothing is reported twice. With an ESLint config, turn on only one of the two.

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

Off by default. To turn it on:

```toml bunfig.toml
[lint.rules]
"@typescript-eslint/no-magic-numbers" = "error" # or "warn"
```

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"@typescript-eslint/no-magic-numbers" = ["error", {
  ignore = [], # list of numbers or strings
  ignoreArrayIndexes = false,
  ignoreDefaultValues = false,
  ignoreClassFieldInitialValues = false,
  ignoreReadonlyClassProperties = false,
  ignoreEnums = false,
  ignoreNumericLiteralTypes = false,
  ignoreTypeIndexes = false,
  enforceConst = false,
  detectObjects = false,
}]
```

{/* End of the generated section. */}

## Examples

Reported:

{/* bad */}
```ts
function total(price: number) {
  return price + price * 0.2;
}
```

Not reported:

{/* good */}
```ts
const TAX_RATE = 0.2;

function total(price: number) {
  return price + price * TAX_RATE;
}
```

Numbers in enums, types and class fields count too. All five are reported:

{/* bad {"count": 5} */}
```ts
enum Status {
  Active = 1,
}

type Level = 2 | 3;

type First = [string, number][0];

class Client {
  readonly retries = 4;
}
```

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `ignore` | `[]` | Numbers that are never reported. `1` doesn't cover `-1`. Write a bigint as a string: `"1n"`. |
| `ignoreArrayIndexes` | `false` | Allow a number as an index: `items[0]`. |
| `ignoreDefaultValues` | `false` | Allow a number as a default value: `function retry(times = 3) {}`. |
| `ignoreClassFieldInitialValues` | `false` | Allow a number as the initial value of a class field that isn't `readonly`. |
| `ignoreReadonlyClassProperties` | `false` | Allow numbers in `readonly` class fields. |
| `ignoreEnums` | `false` | Allow numbers in enum members. |
| `ignoreNumericLiteralTypes` | `false` | Allow a type alias for a number or a union of numbers. |
| `ignoreTypeIndexes` | `false` | Allow a number as an index into a type: `Pair[0]`. |
| `enforceConst` | `false` | Report a number that initializes a `let` or a `var`. |
| `detectObjects` | `false` | Also report numbers in object literals and numbers assigned to a property. |

Not reported with `ignore: [0, 1]`:

{/* good {"options": [{"ignore": [0, 1]}]} */}
```ts
function last(items: string[]) {
  return items.length === 0 ? undefined : items[items.length - 1];
}
```

Not reported with `ignoreArrayIndexes` and `ignoreDefaultValues`:

{/* good {"options": [{"ignoreArrayIndexes": true, "ignoreDefaultValues": true}]} */}
```ts
function pick(items: string[], count = 3) {
  return [items[0], items.slice(count)];
}
```

Not reported with `ignoreEnums`, `ignoreNumericLiteralTypes`, `ignoreTypeIndexes` and `ignoreReadonlyClassProperties`:

{/* good {"options": [{"ignoreEnums": true, "ignoreNumericLiteralTypes": true, "ignoreTypeIndexes": true, "ignoreReadonlyClassProperties": true}]} */}
```ts
enum Status {
  Active = 1,
}

type Level = 2 | 3;

type First = [string, number][0];

class Client {
  readonly retries = 4;
}
```

With `ignoreClassFieldInitialValues` alone, the `readonly` field is still reported:

{/* bad {"options": [{"ignoreClassFieldInitialValues": true}], "count": 1} */}
```ts
class Client {
  retries = 4;
  readonly timeout = 5000;
}
```

Reported with `enforceConst`:

{/* bad {"options": [{"enforceConst": true}]} */}
```ts
let timeout = 5000;
```

Both lines are reported with `detectObjects`:

{/* bad {"options": [{"detectObjects": true}], "count": 2} */}
```ts
const config = { timeout: 5000 };
config.timeout = 3000;
```
