React,TypeScript条件道具

时间:2020-08-02 01:21:29

标签: reactjs typescript

我正在尝试使用两个接口之间的管道类型来创建带有条件道具的React组件。我将其设置如下:

interface BaseProps {
  "aria-label"?: string;
  className?: string;
  onClick?: () => void;
}

interface IconProps extends BaseProps {
  "aria-label": string;
  children: never;
  icon: React.ReactElement;
}

interface ButtonProps extends BaseProps {
  children: React.ReactElement;
}

type Props = ButtonProps | IconProps;

class Button extends React.Component<Props> {
  render(): React.ReactElement {
    const { children, icon, ...rest } = this.props;
    // ERROR: "Property 'icon' does not exist on type '(Readonly<ButtonProps> & Readonly<{ children?: ReactNode; }>) | (Readonly<IconProps> & Readonly<{ children?: ReactNode; }>)'."
  }
}

我似乎无法弄清楚如何实现以下目标:

  1. 有“图标”道具时,强制使用“ aria-label”并禁止儿童
  2. 没有“ icon”道具时,强迫儿童并允许使用“ aria-label”

1 个答案:

答案 0 :(得分:0)

一种方法是在两个变体之间建立并集:

interface VariantWithIconProps {
  icon: React.ReactElement,
  "aria-label": string;
}

interface VariantNoIconProps {
  "aria-label"?: string;
  children: React.ReactNode,
}

type Props = VariantWithIconProps | VariantNoIconProps;

const iconProps: VariantWithIconProps = {
  icon: <svg/>,
  "aria-label": "a",
};
const props1: Props = iconProps;
const props2: VariantNoIconProps = iconProps; // typescript error

const noIconProps1: VariantNoIconProps = {
  children: <div/>
};
const props3: Props = noIconProps1;
const props4: VariantWithIconProps = noIconProps1;  // typescript error

const noIconProps2: VariantNoIconProps = {
  children: <div/>,
  'aria-label': "a"
};
const props5: Props = noIconProps2;
const props6: VariantWithIconProps = noIconProps2;  // typescript error

不幸的是,如果没有解决方法,禁止在接口中禁止属性似乎很容易。