kripod / react-polymorphic-types

Zero-runtime polymorphic component definitions for React
MIT License
195 stars 8 forks source link

Typing a `createHeading('h1')` function #6

Open rafgraph opened 3 years ago

rafgraph commented 3 years ago

Hi, I'm trying to type a create function that returns a fully typed component with ref forwarding and the as prop predefined.

This is needed when using a polymorphic component with CSS-in-JS libraries and other polymorphic components. I'm currently using a createInteractive function in React Interactive, see readme docs, and code.

const StyledInteractiveButton = styled(createInteractive('button'), { color: 'green' });
// OR
<SomePolymorphicComponent as={createInteractive('button')} />

Building off of your <Heading> example in the readme I have the following, which works but only because I'm using any. Also see this codesandbox which has the below code along with a few other attempts. Thanks!

function createHeadingWithRef<
  T extends React.ElementType = typeof HeadingDefaultElement
>(as: T): React.ForwardRefExoticComponent<Omit<HeadingProps<T>, "as">> {
  // without any get TS error on return type of WrappedHeading
  const WrappedHeading: any = React.forwardRef(function <
    T extends React.ElementType = typeof as
  >(
    props: PolymorphicPropsWithoutRef<HeadingOwnProps, T>,
    ref: React.ForwardedRef<Element>
  ) {
    return <Heading {...props} as={as} ref={ref} />;
  });
  return WrappedHeading;
}