@typescript-eslint/prefer-readonly
Require readonly on private members that are only assigned in the constructor
Also called typescript-eslint/prefer-readonly, typescript/prefer-readonly
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.
Configure#
Off by default. This rule needs types, so turning it on makes bun lint type check your code first.
[lint.rules]
"@typescript-eslint/prefer-readonly" = "error" # or "warn"Every option, set to its default:
[lint.rules]
"@typescript-eslint/prefer-readonly" = ["error", {
onlyInlineLambdas = false,
}]Examples#
class Cache {
private entriesMember entries is never reassigned; mark it as readonly. = new Map<string, string>();
#limitMember #limit is never reassigned; mark it as readonly. = 100;
private nameMember name is never reassigned; mark it as readonly.: string;
constructor(name: string, private ttlMember ttl: number is never reassigned; mark it as readonly.: number) {
this.name = name;
}
set(key: string, value: string) {
this.entries.set(key, value);
}
}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:
{ "onlyInlineLambdas": true }No problemsclass Button {
private label = "Save";
}An arrow function is still reported, and so is a member that's declared without a value:
{ "onlyInlineLambdas": true }2 problemsclass Button {
private idMember id is never reassigned; mark it as readonly.: string;
private onClickMember onClick is never reassigned; mark it as readonly. = () => {
console.log("clicked");
};
constructor(id: string) {
this.id = id;
}
}