首页 > 解决方案 > 打字稿:X 类型的参数不可分配给 Y 和 X 类型的参数。X 类型不可分配给 Y

问题描述

对于按钮链接组件,我试图根据传递的道具在 HTMLButtonAttributes 或 HTMLAnchorAttributes 之间进行选择。我对 TypeScript 的了解非常有限。

我有以下类型和接口:

interface CommonButtonProps {
   // custom props
}

export interface ButtonProps extends CommonButtonProps,
    React.ButtonHTMLAttributes<HTMLButtonElement> {}

export interface ButtonLinkProps extends CommonButtonProps,
    React.AnchorHTMLAttributes<HTMLAnchorElement> {
  href: string;
}

export type ButtonOrButtonLinkProps = ButtonProps | ButtonLinkProps;

export const isButtonLink = (props: ButtonOrButtonLinkProps,): props is ButtonLinkProps => guard logic

以及以下带有 ButtonOrButtonLinkProps 的 Button 组件:

export const Button: React.FC<ButtonOrButtonLinkProps> = props => {
  const buttonLink = isButtonLink(props);

  const commonProps = {
  };

  const linkProps: ButtonLinkProps = {
    ...commonProps,
    onClick: (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
      // Do stuff
      if (props.onClick) {
        props.onClick(event); // Error
      }
    },
  };


  const buttonProps: ButtonProps = {
    ...commonProps,
    type: 'button',
    onClick: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
      // Do other stuff
      if (props.onClick) {
        props.onClick(event); // Error
      }
    },
  };

  return (
    <StyledBtn {...(buttonLink ? linkProps : buttonProps)}>
      {children}
    </StyledBtn>
  );
};

以下行引发错误:

  if (props.onClick) {
    props.onClick(event); // Error
  }

“MouseEvent<HTMLButtonElement, MouseEvent>”类型的参数不能分配给“MouseEvent<HTMLButtonElement, MouseEvent> & MouseEvent<HTMLAnchorElement, MouseEvent>”类型的参数。类型“MouseEvent<HTMLButtonElement, MouseEvent>”不可分配给类型“MouseEvent<HTMLAnchorElement, MouseEvent>”。“HTMLButtonElement”类型缺少“HTMLAnchorElement”类型中的以下属性:字符集、坐标、下载、hreflang 等 19 个。

看来当前的类型onClick在此处输入图像描述

为什么 HTMLButtonElement 的 MouseEvent 的事件类型是 HTMLAnchorElement 的&MouseEvent ?我有点期待它是一个工会——要么是一个,要么是另一个?

知道如何解决这个问题吗?

标签: javascriptreactjstypescripttypescript-generics

解决方案


可能你不应该这样做

您的组件的 props 是隔离代码块的公共 API,因此您不想将其扩展得太远。最好的解决方案是不要将所有链接/按钮道具包含在Button道具中,而仅包含必要的道具

但如果你必须

问题是打字稿不明白什么是onClick类型,因为它可能会根据你传递的道具而有所不同。到打字稿出现时props.onClick(execution),道具的类型仍然模棱两可。

解决方案

使用你的 typeguard 让 typescript 知道什么类型的 props

export const Button: React.FC<...> = props => {
  // props is of type `ButtonProps | ButtonLinkProps` here
  // so `onClick` is ambiguous too

  if (isButtonLink(props)) {
    // Do button link stuff
    // props is of type `ButtonLinkProps` here
  } else {
    // Do button stuff
    // props is of type `ButtonProps` here
  }

  // props is again of type `ButtonProps | ButtonLinkProps` here
  
  return (...);
}

打字机上的游乐场链接


推荐阅读