Back to Biomejs

useReadonlyClassProperties

src/content/docs/linter/rules/use-readonly-class-properties.mdx

latest25.7 KB
Original Source

import { Tabs, TabItem } from '@astrojs/starlight/components';

<Tabs> <TabItem label="TypeScript and TSX" icon="seti:typescript"> ## Summary - Rule available since: `v2.1.0` - Diagnostic Category: [`lint/style/useReadonlyClassProperties`](/reference/diagnostics#diagnostic-category) - This rule isn't recommended, so you need to enable it. - This rule has an [**unsafe**](/linter/#unsafe-fixes) fix. - The default severity of this rule is [**information**](/reference/diagnostics#information). - Sources: - Same as [`@typescript-eslint/prefer-readonly`](https://typescript-eslint.io/rules/prefer-readonly)

How to configure

json
{
	"linter": {
		"rules": {
			"style": {
				"useReadonlyClassProperties": "error"
			}
		}
	}
}

Description

Enforce marking members as readonly if they are never modified outside the constructor.

This rule ensures that class properties, especially private ones, are marked as readonly if their values remain constant after being initialized. This helps improve code readability, maintainability, and ensures immutability where applicable.

It can be configured to check only private members or all class properties.

Examples

Invalid

ts
class Container {
    private onlyModifiedInConstructor = 1;
    constructor(
        member1: number,
    ) {
        this.onlyModifiedInConstructor = onlyModifiedInConstructor;
    }
}
<pre class="language-text"><code class="language-text">code-block.ts:2:13 <a href="https://biomejs.dev/linter/rules/use-readonly-class-properties">lint/style/useReadonlyClassProperties</a> <span style="color: #000; background-color: #ddd;"> FIXABLE </span> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Member 'onlyModifiedInConstructor' is never reassigned.</span> <strong>1 │ </strong>class Container &#123; <strong><span style="color: Tomato;">&gt;</span></strong> <strong>2 │ </strong> private onlyModifiedInConstructor = 1; <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong>3 │ </strong> constructor( <strong>4 │ </strong> member1: number, <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Using </span><span style="color: lightgreen;"><strong>readonly</strong></span><span style="color: lightgreen;"> improves code safety, clarity, and helps prevent unintended mutations.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Unsafe fix</span><span style="color: lightgreen;">: </span><span style="color: lightgreen;">Add </span><span style="color: lightgreen;"><strong>readonly</strong></span><span style="color: lightgreen;"> decorator.</span> <strong> 2 │ </strong><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span>private<span style="opacity: 0.8;">·</span><span style="color: MediumSeaGreen;">r</span><span style="color: MediumSeaGreen;">e</span><span style="color: MediumSeaGreen;">a</span><span style="color: MediumSeaGreen;">d</span><span style="color: MediumSeaGreen;">o</span><span style="color: MediumSeaGreen;">n</span><span style="color: MediumSeaGreen;">l</span><span style="color: MediumSeaGreen;">y</span><span style="opacity: 0.8;"><span style="color: MediumSeaGreen;">·</span></span>onlyModifiedInConstructor<span style="opacity: 0.8;">·</span>=<span style="opacity: 0.8;">·</span>1; <strong> │ </strong> <span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span> </code></pre>
ts
class Container {
    constructor(
       private constructorParameter: number,
    ) {
    }
}
<pre class="language-text"><code class="language-text">code-block.ts:3:16 <a href="https://biomejs.dev/linter/rules/use-readonly-class-properties">lint/style/useReadonlyClassProperties</a> <span style="color: #000; background-color: #ddd;"> FIXABLE </span> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Member 'constructorParameter' is never reassigned.</span> <strong>1 │ </strong>class Container &#123; <strong>2 │ </strong> constructor( <strong><span style="color: Tomato;">&gt;</span></strong> <strong>3 │ </strong> private constructorParameter: number, <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong>4 │ </strong> ) &#123; <strong>5 │ </strong> &#125; <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Using </span><span style="color: lightgreen;"><strong>readonly</strong></span><span style="color: lightgreen;"> improves code safety, clarity, and helps prevent unintended mutations.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Unsafe fix</span><span style="color: lightgreen;">: </span><span style="color: lightgreen;">Add </span><span style="color: lightgreen;"><strong>readonly</strong></span><span style="color: lightgreen;"> decorator.</span> <strong> 3 │ </strong><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span>private<span style="opacity: 0.8;">·</span><span style="color: MediumSeaGreen;">r</span><span style="color: MediumSeaGreen;">e</span><span style="color: MediumSeaGreen;">a</span><span style="color: MediumSeaGreen;">d</span><span style="color: MediumSeaGreen;">o</span><span style="color: MediumSeaGreen;">n</span><span style="color: MediumSeaGreen;">l</span><span style="color: MediumSeaGreen;">y</span><span style="opacity: 0.8;"><span style="color: MediumSeaGreen;">·</span></span>constructorParameter:<span style="opacity: 0.8;">·</span>number, <strong> │ </strong> <span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span> </code></pre>
ts
class Container {
    private neverModifiedMember = true;
}
<pre class="language-text"><code class="language-text">code-block.ts:2:13 <a href="https://biomejs.dev/linter/rules/use-readonly-class-properties">lint/style/useReadonlyClassProperties</a> <span style="color: #000; background-color: #ddd;"> FIXABLE </span> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Member 'neverModifiedMember' is never reassigned.</span> <strong>1 │ </strong>class Container &#123; <strong><span style="color: Tomato;">&gt;</span></strong> <strong>2 │ </strong> private neverModifiedMember = true; <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong>3 │ </strong>&#125; <strong>4 │ </strong> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Using </span><span style="color: lightgreen;"><strong>readonly</strong></span><span style="color: lightgreen;"> improves code safety, clarity, and helps prevent unintended mutations.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Unsafe fix</span><span style="color: lightgreen;">: </span><span style="color: lightgreen;">Add </span><span style="color: lightgreen;"><strong>readonly</strong></span><span style="color: lightgreen;"> decorator.</span> <strong> 2 │ </strong><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span>private<span style="opacity: 0.8;">·</span><span style="color: MediumSeaGreen;">r</span><span style="color: MediumSeaGreen;">e</span><span style="color: MediumSeaGreen;">a</span><span style="color: MediumSeaGreen;">d</span><span style="color: MediumSeaGreen;">o</span><span style="color: MediumSeaGreen;">n</span><span style="color: MediumSeaGreen;">l</span><span style="color: MediumSeaGreen;">y</span><span style="opacity: 0.8;"><span style="color: MediumSeaGreen;">·</span></span>neverModifiedMember<span style="opacity: 0.8;">·</span>=<span style="opacity: 0.8;">·</span>true; <strong> │ </strong> <span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span> </code></pre>
ts
class Container {
    #neverModifiedPrivateField = 3;
}
<pre class="language-text"><code class="language-text">code-block.ts:2:5 <a href="https://biomejs.dev/linter/rules/use-readonly-class-properties">lint/style/useReadonlyClassProperties</a> <span style="color: #000; background-color: #ddd;"> FIXABLE </span> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Member '#neverModifiedPrivateField' is never reassigned.</span> <strong>1 │ </strong>class Container &#123; <strong><span style="color: Tomato;">&gt;</span></strong> <strong>2 │ </strong> #neverModifiedPrivateField = 3; <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong>3 │ </strong>&#125; <strong>4 │ </strong> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Using </span><span style="color: lightgreen;"><strong>readonly</strong></span><span style="color: lightgreen;"> improves code safety, clarity, and helps prevent unintended mutations.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Unsafe fix</span><span style="color: lightgreen;">: </span><span style="color: lightgreen;">Add </span><span style="color: lightgreen;"><strong>readonly</strong></span><span style="color: lightgreen;"> decorator.</span> <strong> 2 │ </strong><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="color: MediumSeaGreen;">r</span><span style="color: MediumSeaGreen;">e</span><span style="color: MediumSeaGreen;">a</span><span style="color: MediumSeaGreen;">d</span><span style="color: MediumSeaGreen;">o</span><span style="color: MediumSeaGreen;">n</span><span style="color: MediumSeaGreen;">l</span><span style="color: MediumSeaGreen;">y</span><span style="opacity: 0.8;"><span style="color: MediumSeaGreen;">·</span></span>#neverModifiedPrivateField<span style="opacity: 0.8;">·</span>=<span style="opacity: 0.8;">·</span>3; <strong> │ </strong> <span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span> </code></pre>

Valid

ts
class Container {
    private readonly neverModifiedMember = true;
    private readonly onlyModifiedInConstructor: number;
    readonly #neverModifiedPrivateField = 3;

    public constructor(
        onlyModifiedInConstructor: number,
        private readonly neverModifiedParameter: string,
    ) {
        this.onlyModifiedInConstructor = onlyModifiedInConstructor;
    }
}

Options

checkAllProperties

Checks whether all class properties (including public and protected) should be analyzed. By default, checkAllProperties is set to false.

json
{
	"linter": {
		"rules": {
			"style": {
				"useReadonlyClassProperties": {
					"options": {
						"checkAllProperties": true
					}
				}
			}
		}
	}
}

ts
class Example {
    public constantValue = 42;

    constructor(value: number) {
        this.constantValue = value;
    }
}
<pre class="language-text"><code class="language-text">code-block.ts:2:12 <a href="https://biomejs.dev/linter/rules/use-readonly-class-properties">lint/style/useReadonlyClassProperties</a> <span style="color: #000; background-color: #ddd;"> FIXABLE </span> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Member 'constantValue' is never reassigned.</span> <strong>1 │ </strong>class Example &#123; <strong><span style="color: Tomato;">&gt;</span></strong> <strong>2 │ </strong> public constantValue = 42; <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong>3 │ </strong> <strong>4 │ </strong> constructor(value: number) &#123; <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Using </span><span style="color: lightgreen;"><strong>readonly</strong></span><span style="color: lightgreen;"> improves code safety, clarity, and helps prevent unintended mutations.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Unsafe fix</span><span style="color: lightgreen;">: </span><span style="color: lightgreen;">Add </span><span style="color: lightgreen;"><strong>readonly</strong></span><span style="color: lightgreen;"> decorator.</span> <strong> 2 │ </strong><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span>public<span style="opacity: 0.8;">·</span><span style="color: MediumSeaGreen;">r</span><span style="color: MediumSeaGreen;">e</span><span style="color: MediumSeaGreen;">a</span><span style="color: MediumSeaGreen;">d</span><span style="color: MediumSeaGreen;">o</span><span style="color: MediumSeaGreen;">n</span><span style="color: MediumSeaGreen;">l</span><span style="color: MediumSeaGreen;">y</span><span style="opacity: 0.8;"><span style="color: MediumSeaGreen;">·</span></span>constantValue<span style="opacity: 0.8;">·</span>=<span style="opacity: 0.8;">·</span>42; <strong> │ </strong> <span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span> </code></pre>
ts
class Example {
    constructor(protected constructorParameter: string) {
    }
}
<pre class="language-text"><code class="language-text">code-block.ts:2:27 <a href="https://biomejs.dev/linter/rules/use-readonly-class-properties">lint/style/useReadonlyClassProperties</a> <span style="color: #000; background-color: #ddd;"> FIXABLE </span> ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Member 'constructorParameter' is never reassigned.</span> <strong>1 │ </strong>class Example &#123; <strong><span style="color: Tomato;">&gt;</span></strong> <strong>2 │ </strong> constructor(protected constructorParameter: string) &#123; <strong> │ </strong> <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong> <strong>3 │ </strong> &#125; <strong>4 │ </strong>&#125; <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Using </span><span style="color: lightgreen;"><strong>readonly</strong></span><span style="color: lightgreen;"> improves code safety, clarity, and helps prevent unintended mutations.</span> <strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Unsafe fix</span><span style="color: lightgreen;">: </span><span style="color: lightgreen;">Add </span><span style="color: lightgreen;"><strong>readonly</strong></span><span style="color: lightgreen;"> decorator.</span> <strong> 2 │ </strong><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span><span style="opacity: 0.8;">·</span>constructor(protected<span style="opacity: 0.8;">·</span><span style="color: MediumSeaGreen;">r</span><span style="color: MediumSeaGreen;">e</span><span style="color: MediumSeaGreen;">a</span><span style="color: MediumSeaGreen;">d</span><span style="color: MediumSeaGreen;">o</span><span style="color: MediumSeaGreen;">n</span><span style="color: MediumSeaGreen;">l</span><span style="color: MediumSeaGreen;">y</span><span style="opacity: 0.8;"><span style="color: MediumSeaGreen;">·</span></span>constructorParameter:<span style="opacity: 0.8;">·</span>string)<span style="opacity: 0.8;">·</span>&#123; <strong> │ </strong> <span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span><span style="color: MediumSeaGreen;">+</span> </code></pre> </TabItem> </Tabs>