-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
View: Fix TypeScript types #60919
View: Fix TypeScript types #60919
Conversation
asProp || | ||
( ( typeof onClick !== 'undefined' | ||
? 'button' | ||
: 'div' ) as ElementType ); |
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.
Removed unnecessary type cast.
> = styled.div``; | ||
|
||
View.selector = '.components-view'; | ||
View.displayName = 'View'; |
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.
Explicit assignment of displayName
is no longer needed.
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.
To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
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 makes sense to me since there is no way around generics for actual polymorphic types. Kind of unfortunate to have to rely on "as" IMO but that's a separate discussion for another day about a pre-existing circumstance.
I do wonder if there might be a better temporary solution (even if hacky) if we're planning on addressing this soon. Adding a generic can be hard to undo.
"Addressing this" as in, moving from an Out of scope for this PR, but we should also think about what to do about |
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.
Looking mostly good to me 👍
I wonder if we could have avoided the markup differences, unless I'm missing a good reason to have them in the first place?
Out of scope for this PR, but we should also think about what to do about View in the context of #59418. It's probably a undesirable component to proliferate, and plus it's based on Emotion.
There's some sparse usage of the __experimentalView
component across the plugin directory: https://wpdirectory.net/search/01HW5GNQWJ0EYYKZGAW9PJ0CBD so we could likely discourage it in the future without pain, especially if we head in the direction of abandoning Emotion.
View.displayName = 'View'; | ||
export const View = Object.assign( forwardRef( UnforwardedView ), { | ||
selector: '.components-view', | ||
} ); | ||
|
||
export default View; |
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.
Is there a good reason to continue exporting the default? Can't we just re-export the named export?
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 think I'm ok with removing default exports, but that has kind of been a convention across the package, so it might be better to address as part of a package-wide change.
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.
Indeed, not a blocker for the PR, but definitely something to consider at some point.
{ as, ...restProps }: WordPressComponentProps< {}, T >, | ||
ref: React.ForwardedRef< any > | ||
) { | ||
return <PolymorphicDiv as={ as } ref={ ref } { ...restProps } />; |
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.
Feels a bit off to have PolymorphicDiv
appear in markup now, because it's an internal behavior of View
and it's not immediately clear where it comes from. I wonder if we should keep the same naming externally so resulting markup doesn't change.
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 think "PolymorphicDiv" is a clear label that both conveys intent and is searchable, but would you prefer something prefixed like "ViewPolymorphicDiv"?
Otherwise we need to add some overhead like const styles = { View: styled.div`` }
or whatever to get around the name collision within this file. Which is not worth it IMO, especially since the class names will be completely hashed in prod anyway.
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 just worried about the potential confusion that comes from the fact that the component is called View
but it's visualized in markup as PolymorphicDiv
.
In practice, this could be confusing for folks who are going to be looking for a PolymorphicDiv
component, and it could potentially be an issue for usages who were dynamically targeting selectors (which they, of course, shouldn't do) based on the presence of -View-
in the classname.
But if you feel this shouldn't be an issue because those internals were never official and folks should never have relied on them, then we're good.
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.
Oh ok, it is a non-issue for the selector usage scenario, because the Emotion class names are completely hashed in prod (<div class="css-0 e19lxcc00">
). They're impossible to use as selectors, even hackily.
For the dev mode debugging scenario, in my experience the human-readable Emotion class names are usually a soup of internal variable names, so it's only useful for identifying things when you already know what strings you're looking for.
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 confirming. Let's 🚢 !
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.
LGTM, provided that we're good with the markup changes 🚢
Required for #60796
What?
Fixes type errors related to the
View
component that are surfaced when@types/react
is updated to v18.2.79.Why?
@types/react@18.2.79
is a bit stricter, surfacing a problem in theView
component type. Or more accurately, a problem with how we use theWordPressComponentProps
utility type. It just happened to manifest at the View component, when consumer components likeNavigator
used it polymorphically and triggered actual prop discrepancies betweendiv
andbutton
.This is a minimal illustration of how we need to write our types, for a consumer-provided
as
prop to properly influence the accepted props:I believe this kind of problem could manifest in any of our polymorphic components that use
WordPressComponentProps
to define props without having a generic at the component-level.How?
Reorganize the View component so it can be typed better, and add a generic to better support polymorphism.
Testing Instructions
Type checks should pass in the current package.json setup, as well as this one with updated React types: