Skip to content
NewBun 1.4.5 is out. Release notes
AphrodyBun

Linter · Rules

@typescript-eslint/no-misused-spread

Disallow ... on values that do not spread the way they look

... in an object copies a value's own enumerable properties, and many values have none or the wrong ones. TypeScript accepts all of these:

SpreadWhat you get
A promise, a Map or a Set in an objectAn empty object.
Another iterable in an objectIts own properties, not the values it yields.
An array in an objectThe indexes as keys: { "0": .., "1": .. }.
A function without properties in an objectAn empty object. You probably meant to call it.
A class instance in an objectThe fields, without the class's methods and getters.
A class in an objectOnly its static properties.
A string in an array or a callCode points, which splits an emoji made of several of them.

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/no-misused-spread" = "error" # or "warn"

Every option, set to its default:

bunfig.toml
[lint.rules]
"@typescript-eslint/no-misused-spread" = ["error", {
  allow = [], # list of strings or objects
}]

Examples

Reported:

declare function loadUser(): Promise<{ name: string }>;
const roles = new Map([["admin", true]]);
const tags = ["new", "sale"];

const user = { ...loadUser() };
const access = { ...roles };
const labels = { ...tags };

Not reported:

declare function loadUser(): Promise<{ name: string }>;
const roles = new Map([["admin", true]]);
const tags = ["new", "sale"];

const user = { ...(await loadUser()) };
const access = Object.fromEntries(roles);
const labels = [...tags];

A class instance loses its methods:

class Cart {
  items: string[] = [];
  count() {
    return this.items.length;
  }
}

const copy = { ...new Cart() };

A string in an array:

function letters(name: string) {
  return [...name];
}

Intl.Segmenter splits a string into the characters a reader sees:

function letters(name: string) {
  return Array.from(new Intl.Segmenter().segment(name), part => part.segment);
}

Options

OptionDefaultWhat it does
allow[]Types you can spread. Each is a name, or an object that also says where the type comes from: { "from": "file", "name": .. }, { "from": "lib", "name": .. } or { "from": "package", "name": .., "package": .. }.

Not reported with allow: ["Cart"]:

class Cart {
  items: string[] = [];
  count() {
    return this.items.length;
  }
}

const copy = { ...new Cart() };