# class-methods-use-this

> Require class methods to use `this`

A method that never touches `this` doesn't need an instance, but callers still have to create one to call it. Make it `static`, or move it out of the class as a plain function.

The rule checks methods, getters, setters, and fields that hold a function. Constructors and static members aren't checked. Using `super` counts as using `this`.

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

Off by default. To turn it on:

```toml bunfig.toml
[lint.rules]
"class-methods-use-this" = "error" # or "warn"
```

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

```toml bunfig.toml
[lint.rules]
"class-methods-use-this" = ["error", {
  exceptMethods = [], # list of strings
  enforceForClassFields = true,
  ignoreOverrideMethods = false,
  # ignoreClassesWithImplements = <"all" or "public-fields">,
}]
```

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

## Examples

Reported:

{/* bad */}
```js
class Cart {
  formatPrice(cents) {
    return "$" + (cents / 100).toFixed(2);
  }
}
```

Not reported:

{/* good */}
```js
class Cart {
  static formatPrice(cents) {
    return "$" + (cents / 100).toFixed(2);
  }

  total() {
    return Cart.formatPrice(this.items.reduce((sum, item) => sum + item.cents, 0));
  }
}
```

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `exceptMethods` | `[]` | Method names to skip. Write a private method with its `#`. |
| `enforceForClassFields` | `true` | Also check fields that hold a function, like `format = () => {}`. |
| `ignoreOverrideMethods` | `false` | Don't check members marked `override` in TypeScript. |
| `ignoreClassesWithImplements` | not set | `"all"` skips every member of a class that has an `implements` clause. `"public-fields"` skips only its public members. |

A framework may call a method on the instance whether it uses `this` or not:

{/* good {"options": [{"exceptMethods": ["render", "#label"]}]} */}
```js
class Spinner extends Component {
  render() {
    return "Loading";
  }

  #label() {
    return "Spinner";
  }
}
```

{/* good {"options": [{"enforceForClassFields": false}]} */}
```js
class Cart {
  formatPrice = cents => "$" + (cents / 100).toFixed(2);
}
```

{/* good {"options": [{"ignoreOverrideMethods": true}]} */}
```ts
class Guest extends User {
  override displayName() {
    return "Guest";
  }
}
```

With `"public-fields"`, the interface may ask for `name()`, but it can't ask for the private `prefix()`:

{/* bad {"options": [{"ignoreClassesWithImplements": "public-fields"}], "count": 1} */}
```ts
class Guest implements Named {
  name() {
    return "Guest";
  }

  private prefix() {
    return "Mx.";
  }
}
```
