Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add excludedRunes option to the prefer-const rule #1064

Merged
merged 7 commits into from
Mar 5, 2025

Conversation

baseballyama
Copy link
Member

close part of #818

As explained here, $state also needs to be excluded from the prefer-const rule.
#985 (comment)

Copy link

changeset-bot bot commented Feb 9, 2025

🦋 Changeset detected

Latest commit: 8ecf189

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
eslint-plugin-svelte Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Contributor

github-actions bot commented Feb 9, 2025

Try the Instant Preview in Online Playground

ESLint Online Playground

Install the Instant Preview to Your Local

npm i https://pkg.pr.new/eslint-plugin-svelte@1064

Published Instant Preview Packages:

View Commit

@ota-meshi
Copy link
Member

I still don't understand why you want to ignore $state from svelte/prefer-const rule.

I know that some users want to use let to change value with const value = $state({ value: new Date().toString() });, but I think that user would do the same with const value = { value: new Date().toString() }; which doesn't use $state(). In other words, I think that user would always turn off the prefer-const rule.
So I don't think there's a need to ignore $state from the svelte/prefer-const rule check.

@baseballyama
Copy link
Member Author

We might want to enable prefer-const for plain JavaScript that has nothing to do with Svelte.

In other words, semantically, since $state is something that can be reassigned, we may want to consistently use let for it. However, it’s understandable that some users would prefer to use prefer-const for regular JavaScript outside of that.

(Personally, I always use const consistently, though.😅)

@baseballyama
Copy link
Member Author

In this case, there is no actual reassignment, so prefer-const would allow it to be declared as const. However, semantically, some people may prefer to declare it with let.

export const Time3 = () => {
	// If `$state` has object value,
	// Time3 user cn reassign `value.value` even without reassign logic in this composable.
	// Therefore it can be declare as both `const` / `let`
	const value = $state( { value: new Date().toString() });

	return {
		get value() {
			return value;
		}
	}
}

@ota-meshi
Copy link
Member

I understand that when a user uses $state(), it is clear that the user intends a variable that will be mutated. However, objects that do not use $state() may also be mutable, so for consistency, I think that users who prefer let should also use let for them.
In other words, the prefer-const issue with mutable objects is not a problem specific to $state() (Svelte syntax), so I don't think it should be specially ignored.

@baseballyama
Copy link
Member Author

Therefore, I am considering creating a separate rule, prefer-let. This rule will enforce the consistent use of let.

@baseballyama
Copy link
Member Author

@ota-meshi So, what you’re saying is that extending prefer-const in the first place is unnecessary?

@ota-meshi
Copy link
Member

ota-meshi commented Feb 9, 2025

So, what you’re saying is that extending prefer-const in the first place is unnecessary?

No, I think svelte/prefer-const is necessary.
I don't think there's any need to ignore $state() from the svelte/prefer-const rule check.

Since we don't ignore svelte/prefer-const rule checks for mutable objects regardless of $state(), I think the rule would be inconsistent if we were to ignore only $state() from svelte/prefer-const rule checks.

If a primitive value of $state() is reported with prefer-const, it's just a case of the user using it incorrectly, and I think we can follow it with a different rule (e.g. prefer-let).

@baseballyama
Copy link
Member Author

If a primitive value of $state() is reported with prefer-const, it's just a case of the user using it incorrectly, and I think we can follow it with a different rule (e.g. prefer-let).

I still don’t fully understand this part. Since $state can hold non-primitive values such as object, are there cases where there is no direct reassignment? In such cases, is it correct for const to be enforced? Even if a prefer-let rule were implemented, wouldn’t it conflict with prefer-const, which enforces const?

https://svelte.dev/playground/hello-world?version=5.19.9#H4sIAAAAAAAAE32MzQqDMBAGX2VZCiqIlh6DFXrrO9Qeom4lkMaQrLZFfPcSpT-H0tsy38xOaOSVUOCRtO7h1jvdQkytYmoTTPGiNHkUpwn5YYMXAKav6mBt5kfSHFgtPf3iTW-YDHsUWPjGKctlZSrWxDB4crCHjWfJFMMEoRcQSa0ailKQHQnYbWGGpDJF_qlNYcvVncKPLNxzkdtyWZZsHWT35srYgaFWphWj1APtv1LI_xjhxyJgikx3RsFuoPk8PwFxCBbbPgEAAA==

@ota-meshi
Copy link
Member

The area I have an issue with is the consistency of the rule.

@baseballyama
Copy link
Member Author

I fully understand your perspective.👍

As stated in the documentation, Svelte runes recommend using let. Based on my understanding, some users interpret JavaScript rules as being overridden by Svelte rules.
https://svelte.dev/docs/svelte/$state

In your example, since user does not use runes, I understood that standard JavaScript rules apply (without being overridden by Svelte rules). Therefore, I believed that the behavior of this PR was consistent.

Additionally, based on your reasoning, shouldn’t $props and $derived also consistently use const whenever possible? (I may not yet fully understand this part.)

@ota-meshi
Copy link
Member

I think the reason why $derived should be let is because it is changed from outside.
But $state doesn't really fit that reason.
For primitive values, the user should assign it somewhere, so it won't be reported to prefer-const.
If the reason to use let is that the object is mutable, then I think objects with setters should use let.

Svelte runes recommend using let.

Hmm... I don't think it explicitly says "recommended". I think it's still a matter of user preference 🤔

@baseballyama
Copy link
Member Author

I see. Would adding a config be a good middle ground? Like { enforceState: false }?
I want to accommodate users who wish to use prefer-const in some way but also want to consistently use let for runes.

@ota-meshi
Copy link
Member

I want to accommodate users who wish to use prefer-const in some way but also want to consistently use let for runes.

If there are users requesting it, I think it makes sense to add the option.

@baseballyama
Copy link
Member Author

Got it. In that case, since there are no breaking changes, I will try implementing this option after the v3 release.

@baseballyama baseballyama marked this pull request as draft February 9, 2025 14:12
@baseballyama baseballyama changed the title fix: ignore $state in the prefer-const rule feat: add excludedRunes option to the prefer-const rule Feb 23, 2025
@baseballyama baseballyama marked this pull request as ready for review February 23, 2025 13:44
@baseballyama
Copy link
Member Author

I added excludedRunes option.

@baseballyama baseballyama requested a review from Copilot February 27, 2025 15:35
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

PR Overview

This PR introduces a new configuration option, excludedRunes, for the prefer-const rule so that Svelte reactive values (such as $props, $derived, and now $state) can be ignored during const preference analysis. Key changes include updates to test fixtures, documentation, rule implementation, and the rule’s schema to support the new option.

Reviewed Changes

File Description
packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-const/invalid/option1/test01-errors.yaml Updates to error fixture properties to include line and column details
packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-const/invalid/option2/test01-errors.yaml Updates to error fixture properties to include line and column details
.changeset/sixty-cars-fail.md Changeset entry for the new feature
docs/rules/prefer-const.md Documentation updated to reflect the addition of the excludedRunes option
packages/eslint-plugin-svelte/src/rules/prefer-const.ts Updated rule implementation and schema to accept and use the excludedRunes option
packages/eslint-plugin-svelte/src/rule-types.ts Updated type definitions to include the excludedRunes property

Copilot reviewed 17 out of 17 changed files in this pull request and generated no comments.

Comments suppressed due to low confidence (1)

docs/rules/prefer-const.md:49

  • The configuration property 'ignoreReadonly' in the docs is inconsistent with the rule schema, which defines the property as 'ignoreReadBeforeAssign'. Consider aligning these property names to avoid confusion.
      "ignoreReadonly": true,

Copy link
Member

@ota-meshi ota-meshi left a comment

Choose a reason for hiding this comment

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

LGTM! Thank you!

@ota-meshi ota-meshi merged commit df1647f into main Mar 5, 2025
17 checks passed
@ota-meshi ota-meshi deleted the fix/prefer-const branch March 5, 2025 06:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants