Búsqueda de sitios web

reactjs - Cómo inferir el tipo de evento usando genéricos en un componente polimórfico


Tengo un componente polimórfico en el que intento inferir el tipo de evento mediante genéricos. Desafortunadamente, TypeScript está gritando sobre tipos incompatibles.

import React, { forwardRef } from "react";

export type InferElement<T> = T extends keyof JSX.IntrinsicElements
  ? JSX.IntrinsicElements[T] extends React.DetailedHTMLProps<
      React.AnchorHTMLAttributes<any>,
      infer Elem
    >
    ? Elem
    : never
  : HTMLElement;

export type PolymorphicRef<
  C extends React.ElementType
> = React.ComponentPropsWithRef<C>["ref"];

type ComponentProp<C extends React.ElementType> = {
  component?: C;
};

type PropsToOmit<C extends React.ElementType, P> = keyof (ComponentProp<C> & P);

type PolymorphicComponentProp<
  C extends React.ElementType,
  Props = {}
> = React.PropsWithChildren<Props & ComponentProp<C>> &
  Omit<React.ComponentPropsWithoutRef<C>, PropsToOmit<C, Props>>;

export type PolymorphicComponentPropWithRef<
  C extends React.ElementType,
  Props = {}
> = PolymorphicComponentProp<C, Props> & { ref?: PolymorphicRef<C> };

interface AStaticProps<C extends React.ElementType> {
  onClick?: (event: React.MouseEvent<InferElement<C>, MouseEvent>) => void;
}

type AProps<C extends React.ElementType> = PolymorphicComponentPropWithRef<
  C,
  AStaticProps<C>
>;

type AComponent = <C extends React.ElementType = "div">(
  props: AProps<C>
) => React.ReactElement | null;

const A: AComponent = forwardRef(
  <C extends React.ElementType = "div">(
    { component, onClick, ...rest }: AProps<C>,
    ref?: PolymorphicRef<C>
  ) => {
    const Component = component || "div";

    return (
      <Component {...rest} onClick={onClick}>
        children
      </Component>
    );
  }
);

export default A;

Los tipos de propiedad 'onClick' son incompatibles. El tipo '((event: MouseEvent) => void) | undefined' no es asignable al tipo 'MouseEventHandler | undefined'.

Codesanbox

Respuesta #1

Puedo hacer que el error desaparezca usando Element o HTMLElement en lugar de InferElement<C> en AStaticProps, pero sospecho que no usar tu InferElement significará que perderás mucho del trabajo duro que hiciste en la tipificación:

interface AStaticProps<C extends React.ElementType> {
  onClick?: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
}

Artículos relacionados