# @typescript-eslint/no-unused-vars

> Disallow variables, functions, parameters, imports, and types that are never used

A name that's declared and never read is dead code. It often points at a mistake, like a result you forgot to return, an import left behind after an edit, or a typo that turned one variable into two.

"Used" means read, so a variable that's only assigned to is reported. Exported names aren't. Unlike ESLint's `no-unused-vars`, this rule also checks types, interfaces, and enums, and it knows that `options: Options` uses `Options`.

To keep a name that you don't use, start it with `_`.

This rule is on by default in TypeScript files.

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

## Configure

On by default as a warning. To turn it off:

```toml bunfig.toml
[lint.rules]
"@typescript-eslint/no-unused-vars" = "off" # or "error"
```

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"@typescript-eslint/no-unused-vars" = ["warn", {
  vars = "all", # "all" or "local"
  varsIgnorePattern = "^_",
  args = "after-used", # "all", "after-used" or "none"
  argsIgnorePattern = "^_",
  caughtErrors = "all", # "all" or "none"
  caughtErrorsIgnorePattern = "^_",
  destructuredArrayIgnorePattern = "^_",
  ignoreRestSiblings = true,
  ignoreClassWithStaticInitBlock = false,
  ignoreUsingDeclarations = false,
  reportUsedIgnorePattern = false,
  enableAutofixRemoval = { imports = false },
}]
```

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

## Examples

Reported:

{/* bad {"count": 4} */}
```ts
import { readFile } from "node:fs/promises";

interface Options {
  retries: number;
}

let attempts = 0;
attempts = attempts + 1;

function retry() {}
```

Not reported:

{/* good */}
```ts
import { readFile } from "node:fs/promises";

interface Options {
  retries: number;
}

export async function load(path: string, options: Options) {
  let attempts = 0;
  while (attempts < options.retries) {
    attempts = attempts + 1;
  }
  return readFile(path);
}
```

A value that's only used in a type, through `typeof`, is reported. Nothing reads it when the code runs:

{/* bad */}
```ts
const defaults = { port: 3000 };

export type Settings = typeof defaults;
```

## Options

An option you don't set keeps its default. With an ESLint config you get ESLint's defaults, which have no patterns and set `ignoreRestSiblings` to `false`.

| Option | Default | What it does |
| --- | --- | --- |
| `vars` | `"all"` | `"local"` skips variables in the global scope. The top level of a module isn't the global scope, so this only matters for scripts. |
| `varsIgnorePattern` | `"^_"` | Regular expression for variable names that can be unused. |
| `args` | `"after-used"` | Report unused parameters after the last one that's used. `"all"` reports every unused parameter, `"none"` reports none. |
| `argsIgnorePattern` | `"^_"` | Like `varsIgnorePattern`, for parameters. |
| `caughtErrors` | `"all"` | `"none"` allows an unused `error` in `catch (error)`. |
| `caughtErrorsIgnorePattern` | `"^_"` | Like `varsIgnorePattern`, for the `catch` parameter. |
| `destructuredArrayIgnorePattern` | `"^_"` | Like `varsIgnorePattern`, for names in `const [a, b] = list`. |
| `ignoreRestSiblings` | `true` | Allow unused names next to a `...rest` in object destructuring. |
| `ignoreClassWithStaticInitBlock` | `false` | Allow an unused class that has a `static {}` block, which runs anyway. |
| `ignoreUsingDeclarations` | `false` | Allow unused `using` and `await using` variables, which are disposed of anyway. |
| `reportUsedIgnorePattern` | `false` | Report a name that matches one of the patterns and is used. |
| `enableAutofixRemoval` | `{ "imports": false }` | With `imports: true`, `--fix` removes unused imports. |

You can pass a string, `"all"` or `"local"`, instead of the object. It sets `vars`.

By default, an unused parameter before a used one is allowed, because you can't remove it without moving the others:

{/* good */}
```ts
export const doubled = [1, 2, 3].map((value, index) => index * 2);
```

{/* bad {"options": [{"args": "all"}]} */}
```ts
export const doubled = [1, 2, 3].map((value, index) => index * 2);
```

A name that starts with `_` is unused on purpose. That still applies when you set other options:

{/* good */}
```ts
export function onMessage(_event: string) {}
```

{/* good {"options": [{"args": "all"}]} */}
```ts
export function onMessage(_event: string) {}
```

{/* bad {"options": [{"argsIgnorePattern": "^unused"}]} */}
```ts
export function onMessage(_event: string) {}
```

`ignoreRestSiblings` is for taking properties out of an object:

{/* good */}
```ts
export function publicFields(user: { name: string; password: string }) {
  const { password, ...rest } = user;
  return rest;
}
```

{/* bad {"options": [{"varsIgnorePattern": "^_", "reportUsedIgnorePattern": true}]} */}
```ts
const _port = 3000;

export const url = `http://localhost:${_port}`;
```

With an oxlint config, the rule follows oxlint where the two differ:

- Without an options object, variables and parameters that start with `_` are ignored.
- A value that's only used through `typeof` in a type counts as used, unless `reportVarsOnlyUsedAsTypes` is `true`.
- `fix` replaces `enableAutofixRemoval`. It's `{ "imports": ..., "variables": ... }`, and each is `"off"`, `"suggestion"` (default), `"fix"`, or `"safe-fix"`.
