click-ui icon indicating copy to clipboard operation
click-ui copied to clipboard

Improve typing for `component` prop in components that accept it

Open ariser opened this issue 5 months ago • 3 comments

I spent... some time trying to parse it I don't think this does what you intended to do keyof T is properties of a string in case of T being a tagname. Or it's never if you pass typeof Component.

So copilot is wrong by saying keyof T includes all component prop keys. But it doesn't contain anything useful either.

I believe you do want to use keyof GridContainerProps<T> instead of keyof T here

Originally posted by @ariser in https://github.com/ClickHouse/click-ui/pull/663#discussion_r2303876935

ariser avatar Aug 28 '25 10:08 ariser

Elaborating on the comment.

Current typing, for example in GridContainer:

type GridContainerPolymorphicComponent = <T extends ElementType = "div">(
  props: Omit<ComponentProps<T>, keyof T> & GridContainerProps<T>
) => ReactNode;

The issue with this, is that Omit<ComponentProps<T>, keyof T> doesn't seem to make sense.

Examples:

If I use a user-defined component, keyof T resolves to never:

Image

If I use an HTML tag as a component, keyof T resolves to members of a String instance:

Image

it doesn't make sense to exclude either of these options from ComponentProps<T>, it does nothing. Something clearly doesn't work as intended.

So we need to

  • clarify the intention behind these typings
  • fix them, taking into account current behavior that I described

ariser avatar Aug 28 '25 11:08 ariser

chunk of code I used to verify how these types behave, in case someone needs it

function Example<T extends ElementType>(
  component: T,
  fn: (keysof: keyof T, props: Omit<ComponentProps<T>, keyof T>) => void
) {}

Example(Text, (keysof, props) => {
  keysof;
  props;
});

Example("div", (keysof, props) => {
  keysof;
  props;
});

ariser avatar Aug 28 '25 11:08 ariser

Components that use this pattern for types (including, but not limited to)

  • Text
  • GridContainer
  • Container

ariser avatar Aug 28 '25 11:08 ariser