Skip to content
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

CustomSelectControl: improve props type inferring #64412

Merged

Conversation

meteorlxy
Copy link
Contributor

@meteorlxy meteorlxy commented Aug 10, 2024

What?

Improve props type inferring for CustomSelectControl component.

Why?

The current implementation (introduced in #63985) has some drawbacks:

  1. The option type could be inferred from value and onChange, which is not expected.
  2. The options does not accept immutable array.

How?

Followed the implementation of #64069 :

  1. Make use of NoInfer
  2. Use ReadonlyArray for options

cc @mirka

Testing Instructions

Added type checking in unit tests

Testing Instructions for Keyboard

N/A

Screenshots or screencast

N/A

Copy link

github-actions bot commented Aug 10, 2024

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 props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: meteorlxy <meteorlxy@git.wordpress.org>
Co-authored-by: mirka <0mirka00@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@akasunil akasunil added [Type] Bug An existing feature does not function as intended [Package] Components /packages/components labels Aug 11, 2024
@mirka mirka requested a review from a team August 12, 2024 17:52
Copy link
Member

@mirka mirka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the improvement!

Comment on lines 718 to 727
const onChange: (
changeObject: CustomSelectChangeObject< CustomSelectOption >
) => void = () => {};
const onChangeWithFoo: (
changeObject: CustomSelectChangeObject<
CustomSelectOption & {
foo: string;
}
>
) => void = () => {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we would write these tests without having to import the CustomSelectChangeObject and CustomSelectOption types directly. Consumers outside of this package don't have access to these internal types.

Suggested change
const onChange: (
changeObject: CustomSelectChangeObject< CustomSelectOption >
) => void = () => {};
const onChangeWithFoo: (
changeObject: CustomSelectChangeObject<
CustomSelectOption & {
foo: string;
}
>
) => void = () => {};
const onChange: React.ComponentProps<
typeof UncontrolledCustomSelectControl
>[ 'onChange' ] = () => {};

And for the onChangeWithFoo cases, I think we could simplify it into a more realistic example and just inline it:

		<UncontrolledCustomSelectControl
			label="Label"
			options={ options }
			value={ {
				key: 'narrow',
				name: 'Narrow',
			} }
			// @ts-expect-error: the option type should not be inferred from `onChange`
			onChange={ ( obj ) => obj.foo }
		/>;

Copy link
Contributor Author

@meteorlxy meteorlxy Aug 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

As for the onChangeWithFoo cases, what you provided above should not be what we want.

We need to test if the NoInfer in the onChange method works as expected, so we have to define the type of the onChange prop explicitly.

It should not be a realistic use case for sure, but we still need to test it. So I added some comments to explain it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, you're right. Thanks for the simplification and code comment though, it reads a lot better 👍

@@ -24,7 +24,7 @@ export type CustomSelectOption = {
/**
* The object returned from the onChange event.
*/
type CustomSelectChangeObject< T extends CustomSelectOption > = {
export type CustomSelectChangeObject< T extends CustomSelectOption > = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better if we could remove this export, as noted above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

@meteorlxy meteorlxy requested a review from mirka August 13, 2024 09:21
@@ -689,3 +689,128 @@ describe.each( [
} );
} );
} );

describe( 'Type checking', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not something for this PR, but I wonder if we should start putting these type-checking pseudo-tests in a separate file under /test (types.tsx for example).

Then we could add a global ESLint disable rule for jest/expect-expect and we'll no longer have to do it every time.

Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extracted to #64588

Copy link
Member

@mirka mirka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the nice improvement 🚀

@mirka mirka merged commit 8169dfd into WordPress:trunk Aug 16, 2024
66 of 69 checks passed
@github-actions github-actions bot added this to the Gutenberg 19.1 milestone Aug 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Components /packages/components [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants