【问题标题】:Typescript: Argument of type X is not assignable to parameter of type Y & X. Type X is not assignable to type Y打字稿:X 类型的参数不可分配给 Y 和 X 类型的参数。X 类型不可分配给 Y
【发布时间】:2021-03-02 01:05:56
【问题描述】:

对于按钮链接组件,我试图根据传递的道具在 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' 类型的参数不是 可分配给“MouseEvent & MouseEvent'。类型 'MouseEvent' 不可分配给类型 'MouseEvent'。 “HTMLButtonElement”类型缺少“HTMLAnchorElement”类型的以下属性:字符集、坐标、下载、hreflang 和 19 更多。

似乎onClick 的当前类型是

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

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

【问题讨论】:

标签: javascript reactjs typescript typescript-generics


【解决方案1】:

也许你不应该这样做

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

但如果你必须这样做

问题在于 typescript 不理解 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 (...);
}

Playground link on typeguards

【讨论】:

    猜你喜欢
    • 2021-04-09
    • 2018-02-09
    • 1970-01-01
    • 1970-01-01
    • 2020-04-25
    • 2021-11-01
    • 2017-12-12
    • 1970-01-01
    • 2021-12-06
    相关资源
    最近更新 更多