0

I write React component using TypeScript receiving as prop that may be either HTML tag or React component.

import * as React from 'react';

type MyComponentProps = {
  as?: keyof HTMLElementTagNameMap | React.ComponentType<any>;
} & React.HTMLAttributes<HTMLElement>;

const MyComponent = React.forwardRef<HTMLElement, MyComponentProps>(({ as = 'div', ...props }, ref) => {
  return React.createElement(as, { ref, ...props });
});

And assume we want to render MyComponent as follow:

type WrappedComponentProps = {
  prop1: string;
  prop2: number;
};

const WrappedComponent: React.FC<WrappedComponentProps> = (props) => {
  // some logic
};
<MyComponent as={WrappedComponent} prop1="some string" prop2={10} />

On the last line we can see TS error cause prop1 and prop2 naturally don't exist on MyComponentProps.

So is it possible to declare something like that to be able to pick up wrapped component's props? Here is my pseudocode:

type MyComponentProps =
  | ({
      as?: keyof HTMLElementTagNameMap;
    } & React.HTMLAttributes<HTMLElement>)
  | ({
      as?: React.ComponentType;
    } & React.ComponentProps<as>);

That solution is working and there's no error:

type MyComponentProps =
  | ({
      as?: keyof HTMLElementTagNameMap;
    } & React.HTMLAttributes<HTMLElement>)
  | {
      as?: React.ComponentType<any>;
      [key: string]: any;
    };

But I'd like to describe my type more clearly than just using [key: string]: any.

  • A solution would require generics, which are [not possible to use in tandem with `forwardRef`](https://stackoverflow.com/questions/58469229/react-with-typescript-generics-while-using-react-forwardref). See linked question for alternative ways to use generics. – kelsny Jan 20 '23 at 15:01

0 Answers0