-
Notifications
You must be signed in to change notification settings - Fork 150
refactor: Strengthen Type Safety and Fix Test File Compilation Errors #1015
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
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1015 +/- ##
=======================================
Coverage 96.27% 96.28%
=======================================
Files 46 47 +1
Lines 2472 2531 +59
Branches 1025 1047 +22
=======================================
+ Hits 2380 2437 +57
- Misses 92 94 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking care of this! Just added some comments.
throw new Error('Rule metadata must contain `docs` property'); | ||
} | ||
|
||
return { ...rule, meta: { ...rule.meta, docs } }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question(blocking): Why? I don't fully understand the reason to return docs
within meta
if it was already there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m explicitly specifying docs because the following code results in a type error:
return { ...rule, meta: { ...rule.meta } };
Type '(TestingLibraryPluginDocs & RuleMetaDataDocs) | undefined' is not assignable to type 'TestingLibraryPluginDocs & RuleMetaDataDocs'.
Type 'undefined' is not assignable to type 'TestingLibraryPluginDocs'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But why not returning just rule
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rule.meta.docs
is marked as optional in the return type of ESLintUtils.RuleCreator,
whereas rule.meta.docs
is required in TestingLibraryPluginRuleModule<TMessageIds, TOptions>
.
So I'm narrowing the type explicitly to ensure it satisfies the expected structure.
If we return rule directly, we get the following type error:
Type 'RuleModule<TMessageIds, TOptions, TestingLibraryPluginDocs, RuleListener>' is not assignable to type 'TestingLibraryPluginRuleModule<TMessageIds, TOptions>'.
Types of property 'meta.docs' are incompatible.
Type '(TestingLibraryPluginDocs & RuleMetaDataDocs) | undefined' is not assignable to type 'TestingLibraryPluginDocs & RuleMetaDataDocs'.
Type 'undefined' is not assignable to type 'TestingLibraryPluginDocs & RuleMetaDataDocs'.
Type 'undefined' is not assignable to type 'TestingLibraryPluginDocs'.ts(2322)
if ( | ||
ASTUtils.isIdentifier(node.property) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question(blocking): Why removing the node.property
condition from this if statement? It worked as short-circuiting the evaluation of the expression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I initially tried implementing it like this:
if (
ASTUtils.isIdentifier(node.property) &&
ALL_RETURNING_NODES.some(
(allReturningNode) => allReturningNode === node.property.name
)
)
However, accessing node.property.name caused a type error:
Property 'name' does not exist on type 'PrivateIdentifier | Expression'.
Property 'name' does not exist on type 'MemberExpressionComputedName'.
That’s why I went with the current approach instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But now that you already checked that ASTUtils.isIdentifier(node.property)
for extracting the propertyName
, you could use that for the condition:
if (
propertyName &&
ALL_RETURNING_NODES.some(
(allReturningNode) => allReturningNode === propertyName
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally, I thought the propertyName &&
check was unnecessary, since the comparison inside some — allReturningNode === propertyName
— would implicitly return false if propertyName is null.
But you're right — adding the explicit condition improves readability, so I updated it in a90211d.
It's a minor change, but I refactored a few parts that caught my attention. Please feel free to close this PR if it doesn't meet your expectations. I appreciate your review!
Checks
Changes
update test case types to use rule-tester types.
→ Due to deprecation of TSESLint's
InvalidTestCase
andValidTestCase
.apply
as const
for stricter type safety on query definitions.add explicit return type to
createTestingLibraryRule
for better type safety.→ Because a type error occurred in test files when passing the rule as the second argument to
ruleTester.run
.Context