-
Notifications
You must be signed in to change notification settings - Fork 4.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
TextControl: support generic props type #64293
base: trunk
Are you sure you want to change the base?
TextControl: support generic props type #64293
Conversation
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.
Thanks for the contribution! Makes sense to me in general, left a few notes.
| 'url'; | ||
|
||
export type TextControlProps< | ||
Type extends TextControlPropsType = 'text', |
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 we'll want to use the classic naming strategy for type arguments, and go with T and V for consistency with other instances in the package.
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.
updated
|
||
export type TextControlProps< | ||
Type extends TextControlPropsType = 'text', | ||
Value extends string | number = Type extends 'number' ? number : string, |
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.
It might be better to make this a generic type (e.g. ValueFromType<T>
and then use it in place of the NoInfer<Value>
's. The value type is not really a type argument, but a computed type from "Type", which is the actual type argument.
This would also allow passing a Type explicitly without the need to pass a Value (there's no partial inference). Why you'd want to do that? I have no idea. But it's possible, so...
Edit: now that I think about it, since it has a default it might work if omitted, but I think the general point still stands
Plus this allows an invalid combination, e.g. type text and value number. It could be fixed by repeating the condition in the extends clause, but I think it's cleaner to just compute it in each prop with a utility generic type as I suggested.
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.
updated
@@ -14,27 +29,17 @@ export type TextControlProps = Pick< | |||
/** | |||
* A function that receives the value of the input. | |||
*/ | |||
onChange: ( value: string ) => void; | |||
onChange: ( value: NoInfer< Value > ) => void; |
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.
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 was wondering about this, actually. I had assumed that maybe React does something special with the number input to make it work directly with numbers, but it seems like that assumption is wrong. Unfortunately, that means the PR does not make sense and should be closed.
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.
Ummm 🤔 Not sure if you have noticed it... (assume that you ignored it?)
In fact it's updated to make use of the valueAsNumber
property for type="number"
:
It should work well, and should have great browser support: https://caniuse.com/mdn-api_htmlinputelement_valueasnumber
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.
Just added unit tests for this in c2e292a
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.
Confirming that valueAsNumber
browser support is good.
We should still make sure to support a NaN
case, as it appears to be a potential return value (see docs):
valueAsNumber
A number that represents the value of the element, interpreted as one of the following, in order: A time value, a number, orNaN
if conversion is impossible.
A unit test to cover that scenario would be useful.
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, sorry 🤦 But then this is a breaking change, and I don’t think we can ship it on such a widely used and established component, no? I can’t say this is unambiguously a “bug fix” rather than an enhancement.
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.
Yep, this is a big breaking change. I don't think there's nothing to do here unfortunately. At most expose the valueAsNumber attribute and make the generic depend on it. That seems quite convoluted though.
What?
Fixes #64292
Why?
It would be helpful to infer the
onChange
typeHow?
TextControlProps
a generic typeevent.target.valueAsNumber
orevent.target.value
according to the type oftype
propTesting Instructions
I've added unit tests for type checking.
Testing Instructions for Keyboard
N/A
Screenshots or screencast
Before
After