# no-unused-vars

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

A name that's declared and never read is clutter at best. Often it points to a bug. Maybe you computed a value and then used a different name, or a refactor left an import behind.

"Used" means read. A variable that's only assigned to or incremented isn't used, and neither is a function that only calls itself. Anything you `export` is used.

`--fix-suggestions` removes the declaration, but only if that can't change what the program does: an unused import, function or class, or a variable set to a plain value. `const sent = sendEmail(user);` stays, because removing it would also remove the call. So do parameters, names in a destructuring pattern, and the top level of a script that's neither an ES module nor CommonJS, which a web page can use. With an ESLint config file the suggestions are ESLint's.

An unused import always goes. `import { setup } from "./polyfills";` is removed as a whole, so the module is no longer loaded. `import setup from "./polyfills";` becomes `import "./polyfills";`, which is how you load a module only for its side effects.

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

This rule is on by default in JavaScript files. In TypeScript files, `@typescript-eslint/no-unused-vars` is on instead.

{/* 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]
"no-unused-vars" = "off" # or "error"
```

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"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,
}]
```

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

## Examples

Reported:

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

let saved = 0;

async function save(path, data, options) {
  await writeFile(path, data);
  saved++;
}
```

Not reported:

{/* good */}
```js
import { writeFile } from "node:fs/promises";

let saved = 0;

export async function save(path, data) {
  await writeFile(path, data);
  saved++;
  return saved;
}
```

An unused parameter is only reported if it comes after the last one that's used, because you can't remove the others:

{/* good */}
```js
export const doubled = items.map((item, index) => index * 2);
```

A name that starts with `_` is unused on purpose:

{/* good */}
```js
export function onMessage(_event) {}

const [_first, second] = items;
send(second);
```

A component that only appears in JSX is used:

{/* good */}
```jsx
import Button from "./button";

export const App = () => <Button />;
```

## Options

```toml bunfig.toml
[lint.rules]
no-unused-vars = ["error", { args = "all" }]
```

An option you don't set keeps its default. With an ESLint config the defaults are ESLint's: no patterns, and `ignoreRestSiblings` is `false`.

| Option | Default | What it does |
| --- | --- | --- |
| `vars` | `"all"` | `"local"` skips globals: the names in `/* global */` comments and the top-level variables of a classic script. The top level of a module or a CommonJS file is still checked. |
| `varsIgnorePattern` | `"^_"` | Regular expression for variable names that may be unused. |
| `args` | `"after-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. |

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

With `{ "args": "all" }`, an unused parameter before a used one is reported too:

{/* bad {"options": [{"args": "all"}]} */}
```js
export const doubled = items.map((item, index) => index * 2);
```

The `"^_"` patterns still apply, so `_item` isn't:

{/* good {"options": [{"args": "all"}]} */}
```js
export const doubled = items.map((_item, index) => index * 2);
```

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

{/* good */}
```js
const { password, ...publicUser } = user;
send(publicUser);
```

{/* bad {"options": [{"ignoreRestSiblings": false}]} */}
```js
const { password, ...publicUser } = user;
send(publicUser);
```

{/* bad {"options": [{"varsIgnorePattern": "^_", "reportUsedIgnorePattern": true}]} */}
```js
const _timeout = 500;
wait(_timeout);
```

By default, a name in a `/* global */` comment that the file never uses is reported too:

{/* bad */}
```js
/* global analytics */

console.log("ready");
```

{/* good {"options": ["local"]} */}
```js
/* global analytics */

console.log("ready");
```
