/** * The goal of these types is to make sure that our polymorphic components accept * the correct attributes, and any ref passed onto the polymorphic component has * the correct type. * * For example, when you pass `as="a"`, it should accept an `href` attribute and, * the `ref` should be of type `HTMLAnchorElement`. * * If you pass `as="button"` instead, it should not accept `href` and the `ref` * should be of type `HTMLButtonElement`. * * * Taken from: * https://blog.logrocket.com/build-strongly-typed-polymorphic-components-react-typescript/ */ /** * A generic that is used to capture the `as` prop value */ type AsProp = { as?: C; }; /** * A type of the `as` prop, plus any custom defined props. */ type PropsToOmit = keyof (AsProp & P); /** * Adds a typed `as` prop to a list of props. */ type PolymorphicComponentProp> = React.PropsWithChildren> & Omit, PropsToOmit>; /** * Type to capture the `ref` prop type from the element type * passed into the `as` prop. */ export type PolymorphicRef = React.ComponentPropsWithRef['ref']; /** * Usage example: * * ```tsx * type MyComponentProps = PolymorphicComponentPropWithRef< * C, * { myProp: string } * > * * const MyComponent: ( * props: MyComponentProps * ) => React.ReactElement | null = React.forwardRef( * ( * { children, as, myProp }: MyComponentProps, * ref?: MyComponentProps['ref'] * ) => { * ... * } * ) * ``` */ export type PolymorphicComponentPropWithRef> = PolymorphicComponentProp & { ref?: PolymorphicRef; }; export {};