react-select-async-paginate icon indicating copy to clipboard operation
react-select-async-paginate copied to clipboard

feat: make wrapMenuList generic

Open mihkeleidast opened this issue 3 years ago • 5 comments

This makes the wrapMenuList function generic.

Currently wrapping custom components with wrapMenuList is quite difficult in TypeScript, as it almost always requires type casting. It neither accepts a generic MenuList component, nor returns one that is suitable for SelectComponentsConfig. This is evident from the code in this repository, too, as the returned components object needed a type cast before.

By making the function generic and return a generic component, no type casts are necessary on the outside. There are still some required here internally in two places:

  • the innerRef prop signature does not match with what react-select itself uses, but this should be fine, as React really allows both signatures.
  • in tests, the props object is not a full props object, now that it extends MenuListProps, but for testing purposes it should not matter either.

mihkeleidast avatar Sep 14 '22 11:09 mihkeleidast

Hello. Thanks for your work. I'm working now with improvement of typings in feature/mocks_in_tests branch. I'll consider your PR after finish.

vtaits avatar Sep 14 '22 12:09 vtaits

Cheers, there seems to be something similar in there indeed, let's see if it resolves all issues. Is there an ETA on when that might land?

mihkeleidast avatar Sep 14 '22 12:09 mihkeleidast

I'll try to finish this week.

vtaits avatar Sep 14 '22 12:09 vtaits

Hello. Sorry for the long wait. Check please new version.

vtaits avatar Oct 06 '22 11:10 vtaits

Hi @vtaits, no worries about the wait. I tested your changes out, the function still did not want to accept a generic component - for that, the function itself needs to be generic. I updated my branch with the necessary changes - does this seem fine to you?

mihkeleidast avatar Oct 06 '22 11:10 mihkeleidast

Hey @vtaits, pinging again - can we proceed with this in some way, or should I change anything?

mihkeleidast avatar Dec 01 '22 12:12 mihkeleidast

Hello. MenuList in react-select is generic. So the result of wrapMenuList function should be a generic component. In your changes wrapMenuList is generic, but its result isn't.

https://github.com/JedWatson/react-select/blob/master/packages/react-select/src/components/Menu.tsx#L436

Can you describe the task you're solving?

vtaits avatar Dec 05 '22 11:12 vtaits

I have a custom generic MenuList component that I'm trying to pass into wrapMenuList without any type casting.

export const MenuList = <Option extends SelectOptionType, IsMulti extends false, Group extends GroupBase<Option>>(
  props: MenuListProps<Option, IsMulti, Group>,
) => {
  return <components.MenuList {...props} />;
};

I don't understand your point about the result not being generic - in my testing, it does return a generic component, as expected, because the returned WrappedMenuList component uses the same generic props args from wrapMenuList.

Here's what I see in my editor after the changes, wrapMenuList seems to infer the correct return type from the passed component: image

mihkeleidast avatar Dec 05 '22 12:12 mihkeleidast

@mihkeleidast

It will work if you make type of MenuList the same as components.MenuList:

export const MenuList = <Option, IsMulti extends boolean, Group extends GroupBase<Option>>(
  props: MenuListProps<Option, IsMulti, Group>,
) => {
  return <components.MenuList {...props} />;
};

https://github.com/JedWatson/react-select/blob/3aee85cb8c5d045d47d45b0f9ebd0c58d4593c42/packages/react-select/src/components/Menu.tsx#L436

vtaits avatar Dec 12 '22 08:12 vtaits

@vtaits but I don't want to use the defaults - the whole point of generics is so those arguments could be customized, isn't it? The code example I provided above removed the custom code inside the component that needs those customized arguments to work properly. I did not think it was necessary to show all of my complex code, as the issue is only with generics.

mihkeleidast avatar Dec 12 '22 08:12 mihkeleidast

I didn't notice that react-select accepts your format of function.

I tried to do something more generic like

function wrapMenuList<T>(MenuList: T): T {}

But there were other problems.

Your changes are published in version 0.7.1.

vtaits avatar Dec 12 '22 19:12 vtaits

Cheers, thanks for merging!

mihkeleidast avatar Dec 13 '22 07:12 mihkeleidast