Skip to content

feat: port @typescript-eslint/prefer-readonly rule#456

Merged
hardfist merged 1 commit intomainfrom
feat/port-rule-prefer_readonly-20260204
Feb 5, 2026
Merged

feat: port @typescript-eslint/prefer-readonly rule#456
hardfist merged 1 commit intomainfrom
feat/port-rule-prefer_readonly-20260204

Conversation

@fansenze
Copy link
Copy Markdown
Contributor

@fansenze fansenze commented Feb 4, 2026

Summary

Port the @typescript-eslint/prefer-readonly rule from typescript-eslint to rslint.

This rule enforces that private class members never reassigned outside the constructor should be marked as readonly.

  • Detects private/# members that are only read (not written) outside constructor
  • Supports onlyInlineLambdas option to only check arrow function members
  • Provides autofix to insert readonly modifier
  • Handles type annotation widening for literal types when constructor assigns
  • Supports nested class declarations/expressions with proper scope tracking
  • Handles intersection/union types and TypeParameter (this keyword) resolution
  • Adds ReportRangeWithFixes to RuleContext for range-based fix reporting

Related Links

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @fansenze, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances rslint's TypeScript linting capabilities by integrating the prefer-readonly rule. This addition promotes better code maintainability and clarity by identifying and automatically fixing private class members that can be safely declared as readonly, thereby preventing accidental reassignments and improving type safety. The implementation includes comprehensive support for various TypeScript language features and provides an improved mechanism for rules to suggest fixes.

Highlights

  • New Linter Rule: The @typescript-eslint/prefer-readonly rule has been ported to rslint, enforcing that private class members never reassigned outside the constructor should be marked as readonly.
  • Autofix Support: The new rule supports autofix, which automatically inserts the readonly modifier. It also includes type annotation widening for literal types when necessary.
  • Advanced Type Analysis: The rule incorporates sophisticated type-aware analysis, supporting the onlyInlineLambdas option, nested class declarations/expressions, intersection/union types, and this keyword resolution.
  • Linter Core Enhancement: The RuleContext has been extended with ReportRangeWithFixes to allow rules to report diagnostics with associated fixes based on a specific text range.
Changelog
  • internal/config/config.go
    • Added import for the new prefer_readonly rule.
    • Registered the @typescript-eslint/prefer-readonly rule in the global rule registry.
  • internal/linter/linter.go
    • Implemented the ReportRangeWithFixes function within the linter's RunLinterInProgram to handle range-based fix reporting from rules.
  • internal/plugins/typescript/rules/prefer_readonly/prefer_readonly.go
    • New file: Implements the core logic for the prefer-readonly rule.
    • Includes functions for parsing rule options, managing class scopes, tracking variable modifications, and determining type relations.
    • Provides helper functions for AST node manipulation and type checking.
    • Defines the PreferReadonlyRule with listeners for class declarations, expressions, constructors, and function scopes to detect violations.
    • Implements reportViolations and buildFixes to generate diagnostics and autofixes, including type widening for literal types.
  • internal/plugins/typescript/rules/prefer_readonly/prefer_readonly_test.go
    • New file: Contains extensive Go-based unit tests for the prefer-readonly rule.
    • Includes 28 valid test cases covering already readonly members, modified members, destructuring, increment/decrement, accessors, intersection/union types, and nested classes.
    • Includes 20 invalid test cases covering private static/instance members, private fields, constructor parameters, onlyInlineLambdas option, literal type widening, type annotations, overlapping classes, optional chaining, and non-null assertions, all with expected autofix outputs.
  • internal/rule/rule.go
    • Added ReportRangeWithFixes field to the RuleContext struct, providing a new method for rules to report diagnostics with associated fixes for a specific text range.
  • packages/rslint-test-tools/rstest.config.mts
    • Uncommented the entry for ./tests/typescript-eslint/rules/prefer-readonly.test.ts to enable JavaScript integration tests for the new rule.
Activity
  • The pull request introduces a new linter rule, prefer-readonly, for TypeScript.
  • The rule's implementation and its comprehensive Go test suite have been added.
  • Changes were made to the core linter and rule context to support range-based autofix reporting.
  • The rstest.config.mts file was updated to include the new rule in the JavaScript integration tests.
  • The PR description indicates that the code was generated with Claude Code.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@fansenze fansenze force-pushed the feat/port-rule-prefer_readonly-20260204 branch from 39de93f to f462ce2 Compare February 4, 2026 06:19
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request ports the @typescript-eslint/prefer-readonly rule. The implementation is comprehensive, covering many edge cases and including an autofix. The accompanying tests are also thorough. I've found a few areas for improvement: one potential for flaky tests due to non-deterministic ordering, a minor typo, and some code duplication in the linter core that could be refactored for better maintainability. Overall, this is a great contribution.

@fansenze fansenze changed the title feat(linter): port @typescript-eslint/prefer-readonly rule feat: port @typescript-eslint/prefer-readonly rule Feb 4, 2026
@fansenze fansenze force-pushed the feat/port-rule-prefer_readonly-20260204 branch 5 times, most recently from 3e6b4c1 to 1b1f821 Compare February 4, 2026 08:00
@fansenze fansenze requested a review from hardfist February 4, 2026 08:36
@hardfist hardfist force-pushed the feat/port-rule-prefer_readonly-20260204 branch from 1b1f821 to 200e5ce Compare February 4, 2026 08:59
@hardfist hardfist closed this Feb 4, 2026
@hardfist hardfist reopened this Feb 4, 2026
@hardfist hardfist enabled auto-merge (squash) February 5, 2026 05:34
@hardfist hardfist merged commit 174b322 into main Feb 5, 2026
14 checks passed
@hardfist hardfist deleted the feat/port-rule-prefer_readonly-20260204 branch February 5, 2026 05:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants