-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
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
[core] Type ref for components #15199
Conversation
No bundle size changes comparing 8db4931...533e32a |
This was technically incorrect since the override component didn't receive the props used in the parents but only excess props
d46755a
to
21572a8
Compare
packages/material-ui/src/index.d.ts
Outdated
@@ -13,6 +13,7 @@ export type StandardProps<C, ClassKey extends string, Removals extends keyof C = | |||
> & | |||
StyledComponentProps<ClassKey> & { | |||
className?: string; | |||
ref?: C extends { ref?: infer RefType } ? RefType : React.Ref<unknown>; |
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 assumes that the component forwards the ref.
@@ -6,7 +6,7 @@ export interface BadgeProps | |||
children: React.ReactNode; | |||
badgeContent?: React.ReactNode; | |||
color?: PropTypes.Color | 'error'; | |||
component?: React.ElementType<BadgeProps>; | |||
component?: React.ElementType<React.HTMLAttributes<HTMLDivElement>>; |
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.
See commit description of 1f2505a
5c47e11
to
e9f0390
Compare
Just a heads up that I'm very busy with work right now and it may be a while before I'll have cycles to look at this. I hadn't heard about the union distribution perf regression, is there a TS issue for that? |
|
Types ref for all components not using generic props as
unknown
Finishes on point in #14415
rationale
See https://github.com/eps1lon/typescript-react-ref-issue/blob/626f5197601c35a13e1207a8f4ab7e029454ecb6/index.tsx for current state of
ref
in React.Options
We have three options when declaring the type for the ref attribute:
unknown
HTMLElement
instead ofHTMLInputElement
evaluation
It allows reading as
HTMLInputElement
while it's actually assigned toHTMLDivElement
<Paper component="span" ref={divRef} />
would pass but might throw.It's most likely very rare since the usual suspects for DOM escape hatches
are focus, measuring and
input.value
read/write.The bigger issue would be passing a class component which is definitely wrong
WRT to types.
EventTarget
but that type doesn't offer any value WRT measuringGiven that 1, 2 and 3 allow assigning wrong refs with
component
overridebut only 1 allows full type safety at compile time with type narrowing we use
unknown
until we can infer the ref type from thecomponent
override.There's not much the compiler can do for DX at the moment. Type safety comes
from how you declare the type. We just make sure you can.
Why not just use the generic props approach?
Given that unions props won't work very good with hocs (require distributive Pick/Omit which have extremely bad perf in ts 3.4.1) it's not certain we can stick with that approach. That's why I rather not immediately apply it to the whole codebase until necessary.
It might also be better to rethink ref inference in those components given that too specific refs reject more abstract refs.
props spreading between material-ui components
Spreading props from one component to the other works flawlessly only if both are from the same "generation". One generation includes components using non-generic components (which have
Ref<unknown>
) the other includes components using generic props which infer their ref type. It might also cause some issues for components with generic props if the refs mismatch or are more abstract.https://github.com/mui-org/material-ui/pull/15199/files#diff-e5a9e405d750f736e98750ee9c4a8eabR39 showcases this issue.
TODO
/cc @pelotom