@typescript-eslint/unbound-method

Disallow taking a method off its object without binding it

needs types

Also called typescript-eslint/unbound-method, typescript/unbound-method

A method gets its this from how it's called. If you store user.greet in a variable or pass it as a callback, it's later called without the object, so this is undefined and the first this.name throws.

Calling the method, comparing it, testing it in a condition, and typeof are fine. So are properties that hold an arrow function, methods declared with this: void, and built-in functions that don't use this, such as console.log, Math.max, and JSON.parse.

bun lint --type-aware turns this rule on in TypeScript files.

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/unbound-method" = "error" # or "warn"

Every option, set to its default:

bunfig.toml
[lint.rules]
"@typescript-eslint/unbound-method" = ["error", {
  ignoreStatic = false,
}]

Examples#

example.ts3 problems
class User {
  name = "Ada";
  greet() {
    return `Hello ${this.name}`;
  }
}

const user = new User();
const greet = user.greet;
const { greet: hello } = user;
setTimeout(user.greet, 100);
example.tsNo problems
class User {
  name = "Ada";
  greet() {
    return `Hello ${this.name}`;
  }
  wave = () => `${this.name} waves`;
  static create(this: void) {
    return new User();
  }
}

const user = new User();
const greet = user.greet.bind(user);
setTimeout(() => user.greet(), 100);
setTimeout(user.wave, 100);
const create = User.create;
const log = console.log;

Options#

OptionDefaultWhat it does
ignoreStaticfalseDon't check static methods.

Id.next doesn't use this, but it's reported unless ignoreStatic is on:

example.ts1 problem
class Id {
  static next() {
    return crypto.randomUUID();
  }
}

const ids = [1, 2, 3].map(Id.next);