@typescript-eslint/no-unused-vars

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

warn by defaultfixable

Also called typescript-eslint/no-unused-vars, typescript/no-unused-vars

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.

Configure#

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

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

Every option, set to its default:

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 },
}]

Examples#

example.ts4 problems
import { readFile } from "node:fs/promises";

interface Options {
  retries: number;
}

let attempts = 0;
attempts = attempts + 1;

function retry() {}
example.tsNo problems
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:

example.ts1 problem
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.

OptionDefaultWhat 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.
ignoreRestSiblingstrueAllow unused names next to a ...rest in object destructuring.
ignoreClassWithStaticInitBlockfalseAllow an unused class that has a static {} block, which runs anyway.
ignoreUsingDeclarationsfalseAllow unused using and await using variables, which are disposed of anyway.
reportUsedIgnorePatternfalseReport 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:

example.tsNo problems
export const doubled = [1, 2, 3].map((value, index) => index * 2);
example.tswith { "args": "all" }1 problem
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:

example.tsNo problems
export function onMessage(_event: string) {}
example.tswith { "args": "all" }No problems
export function onMessage(_event: string) {}
example.tswith { "argsIgnorePattern": "^unused" }1 problem
export function onMessage(_event: string) {}

ignoreRestSiblings is for taking properties out of an object:

example.tsNo problems
export function publicFields(user: { name: string; password: string }) {
  const { password, ...rest } = user;
  return rest;
}
example.tswith { "varsIgnorePattern": "^_", "reportUsedIgnorePattern": true }1 problem
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".