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
chore: Safe typing for attribute editor #1517
Conversation
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #1517 +/- ##
=======================================
Coverage 93.98% 93.98%
=======================================
Files 642 642
Lines 17334 17338 +4
Branches 5695 5695
=======================================
+ Hits 16291 16295 +4
Misses 973 973
Partials 70 70
☔ View full report in Codecov by Sentry. |
src/attribute-editor/row.tsx
Outdated
@@ -34,7 +34,10 @@ function render<T>( | |||
itemIndex: number, | |||
slot: AttributeEditorProps.FieldRenderable<T> | React.ReactNode | undefined | |||
) { | |||
return typeof slot === 'function' ? slot(item, itemIndex) : slot; | |||
if (typeof slot === 'function') { | |||
return (slot as AttributeEditorProps.FieldRenderable<T>)(item, itemIndex); |
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.
What is happening here? Isn't typescript by itself can figure that this is a function? (from typeof slot === 'function'
)
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.
From the PR description
This PR removes unsafe usages of the any type
But I do not see any removed any's in this diff...
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.
From typeof slot === 'function'
, Typescript infers the type as (item: T, itemIndex: number) => any
. I could not find out precisely why it ends up with that type, but it is caused by the presence of React.ReactNode
in line 35.
While the any
type of the returned value of this function is not directly visible in the code, the rule still detects its implicit presence and prevents us from returning an any-typed value. With this new code, the return type of the render
function is now React.ReactNode
.
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.
In this case I would rather cast the return value than the function:
return slot(item, itemIndex) as React.ReactNode
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.
If we assert the type of the return value, we have to keep that type assertion in sync with the definition of the return type of FieldRenderable
, which sounds more risky to me than keeping only FieldRenderable
in sync only across line 35 and line 38
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.
This is unsafe either way. We are not fixing any errors, just making the linter happy (which is another big discussion if these rules actually useful).
I prefer the shorter option because it is more readable, cannot see any runtime hazards, really.
When looking into this PR I also learned where this strange any
is coming from. ReactNode
types are incorrect in our version. Related PR DefinitelyTyped/DefinitelyTyped#56210, "Remove {} from ReactFragment" is the change we need
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.
Alternatively, we can write a separate typeguard function
function isSlotFunction(slot: unknown) slot is AttributeEditorProps.FieldRenderable<T> {
return typeof slot == 'function'
}
...
if (isSlotFunction(slot)) {
return slot(item, itemIndex);
}
return slot;
This is also safe and readable to my standards
…ny/attribute-editor
Description
This PR removes unsafe usages of the
any
type from the Attribute Editor component's folder. It also enables an ESLint rule to prevent future unsafe usages there.Related links, issue #, if available: n/a
How has this been tested?
Review checklist
The following items are to be evaluated by the author(s) and the reviewer(s).
Correctness
CONTRIBUTING.md
.CONTRIBUTING.md
.Security
checkSafeUrl
function.Testing
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.