# @typescript-eslint/prefer-readonly

> Require `readonly` on private members that are only assigned in the constructor

A private member can only be assigned inside its class. If nothing there assigns it after the constructor, it never changes. `readonly` says so, and then TypeScript rejects an assignment that someone adds later by mistake.

The rule checks `private` fields and `#private` fields, including static ones, and `private` constructor parameters. Assignments, `++`, `--`, `delete`, and destructuring into the member count as changes. Changing what's inside the value, such as `this.entries.set(...)`, doesn't.

`--fix` adds `readonly`.

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

## Configure

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

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

Every option, set to its default:

```toml bunfig.toml
[lint.rules]
"@typescript-eslint/prefer-readonly" = ["error", {
  onlyInlineLambdas = false,
}]
```

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

## Examples

Reported:

{/* bad {"count": 4} */}
```ts
class Cache {
  private entries = new Map<string, string>();
  #limit = 100;
  private name: string;

  constructor(name: string, private ttl: number) {
    this.name = name;
  }

  set(key: string, value: string) {
    this.entries.set(key, value);
  }
}
```

Not reported:

{/* good */}
```ts
class Cache {
  private readonly entries = new Map<string, string>();
  readonly #limit = 100;
  private hits = 0;
  size = 0;

  constructor(private readonly ttl: number) {}

  get(key: string) {
    this.hits++;
    return this.entries.get(key);
  }
}
```

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `onlyInlineLambdas` | `false` | Skip members that are declared with a value other than an arrow function. |

With `onlyInlineLambdas: true`, this isn't reported:

{/* good {"options": [{"onlyInlineLambdas": true}]} */}
```ts
class Button {
  private label = "Save";
}
```

An arrow function is still reported, and so is a member that's declared without a value:

{/* bad {"options": [{"onlyInlineLambdas": true}], "count": 2} */}
```ts
class Button {
  private id: string;
  private onClick = () => {
    console.log("clicked");
  };

  constructor(id: string) {
    this.id = id;
  }
}
```
