@typescript-eslint/prefer-destructuring

Require destructuring to read a property or an element into a variable

fixableneeds types

Also called typescript-eslint/prefer-destructuring, typescript/prefer-destructuring

const name = user.name writes name twice. const { name } = user writes it once, and the next property you need goes into the same statement.

This is prefer-destructuring with types. const [first] = items only works if items can be iterated, so items[0] is reported only when the type of items is iterable or any. A declaration with a type annotation is left alone by default.

With bunfig.toml, turning this rule on runs it in TypeScript files and prefer-destructuring in JavaScript files, so nothing is reported twice. With an ESLint config, turn the other rule off when you use this one.

A property is only reported if the variable has the same name. An element is only reported if the index is a literal whole number, such as items[0].

--fix rewrites const name = user.name. Elements and plain assignments are reported but not fixed.

Configure#

Off by default. This rule needs types, so turning it on makes bun lint type check your code first.

bunfig.toml
[lint.rules]
"@typescript-eslint/prefer-destructuring" = "error" # or "warn"

Every option, set to its default. The ones that are commented out are unset by default.

bunfig.toml
[lint.rules]
"@typescript-eslint/prefer-destructuring" = [
  "error",
  {
    AssignmentExpression = { array = true, object = true },
    VariableDeclarator = { array = true, object = true },
    # object = true,
    # array = true,
  },
  {
    enforceForRenamedProperties = false,
    enforceForDeclarationWithTypeAnnotation = false,
  },
]

Examples#

example.ts3 problems
declare const user: { name: string; email: string };
declare const items: string[];
let email: string;

const name = user.name;
const first = items[0];
email = user.email;
example.tsNo problems
declare const user: { name: string; email: string };
declare const items: string[];
declare const scores: { 0: number; 1: number };
let email: string;

const { name } = user;
const [first] = items;
({ email } = user);

const best = scores[0]; // not iterable
const label: string = user.name; // has a type annotation

Options#

The rule takes two objects. The first says what to check, and the second has the two enforceFor options.

bunfig.toml
[lint.rules]
"@typescript-eslint/prefer-destructuring" = [
  "error",
  { object = true, array = false },
  { enforceForRenamedProperties = true },
]
OptionDefaultWhat it does
objecttrueReport properties: const name = user.name.
arraytrueReport elements: const first = items[0].
enforceForRenamedPropertiesfalseAlso report a property that goes into a variable with another name, a computed key, and a number key of an object that isn't iterable.
enforceForDeclarationWithTypeAnnotationfalseAlso report declarations that have a type annotation. They aren't fixed.

If you pass the first object, a key you leave out is false. With { object: true }, elements aren't reported:

example.tswith { "object": true }No problems
declare const items: string[];

const first = items[0];

With enforceForRenamedProperties, both of these are reported:

example.tswith { "object": true }, { "enforceForRenamedProperties": true }2 problems
declare const user: { name: string };
declare const scores: { 0: number; 1: number };

const label = user.name;
const best = scores[0];

With enforceForDeclarationWithTypeAnnotation, this is reported too:

example.tswith { "object": true }, { "enforceForDeclarationWithTypeAnnotation": true }1 problem
declare const user: { name: string };

const name: string = user.name;

To treat declarations and assignments differently, give the first object the keys VariableDeclarator and AssignmentExpression, each with its own object and array. With both off for AssignmentExpression, this isn't reported:

example.tswith { "VariableDeclarator": { "object": true, "array": true }, "AssignmentExpression": { "object": false, "array": false } }No problems
declare const user: { email: string };
let email: string;

email = user.email;