如何根据与打字稿反应的其他道具使反应道具成为可选和必需的

问题描述 投票:0回答:1

我有一个反应按钮容器组件,它根据用户使用 prop 提供的类型返回常规按钮或图标按钮或仅图标按钮。以下是

ButtonContainer
组件以及
Props

的相关类型定义
type ButtonWrapperProp = {
    label?:string;
    icon?:React.ReactNode;
    onClick:()=>void;
    type:'text'|'icon'|'iconOnly';

}

export const ButtonContainer = (props: ButtonWrapperProps) => {
    const {
        type = 'text',
        onClick,
        icon = <></>,
        label = '',
    } = props;

    const rendorButton = () => {
        switch (type) {
            case 'text':
                return (
                    <Button onClick={onClick}>{label}  <Button/>
                );

            case 'iconOnly':
                return (
                     <IconButton onClick={onClick}>
                       {icon}
                     </IconButton>
                );

            case 'icon':
                return (
                     <Button startIcon={icon}>
                       {label}
                     </Button>
                );

            default:
                return (
                    <Button onClick={onClick}>{label}  <Button/>
                );
        }
    };
    return <>{rendorButton()}</>;
};

以下是我如何使用ButtonContainer组件

<ButtonContainer type="iconOnly" onClick={onClick} icon={<DeleteIcon />}/>
<ButtonContainer type="text" onClick={onClick} label='Text button'/>
<ButtonContainer type="icon" onClick={onClick} label='Text and icon button' icon={<DeleteIcon />}/>

在上面的代码中, icon 属性是可选的,因为它仅由图标按钮和带有图标的常规按钮使用。我想要的是,仅当从

icon
传递的类型是
ButtonConatiner
并且传递给
text
的类型是
ButtonCOntainer
icon
时,才使
iconOnly
道具成为可选道具,它应该是必需的道具

javascript reactjs typescript frontend web-frontend
1个回答
0
投票

我会选择一个受歧视的工会

type 属性充当鉴别器,允许您将 ButtonWrapperProps 缩小为联合成员。

另请注意,我可以为每个工会成员设置所需的属性,这给我在使用站点上提供了良好的体验 - 设置类型后,TS 足够智能地提示需要哪些附加道具。


type TextButtonProps = {
  type:'text'
  label:string;
  onClick:()=>void;
}

type IconOnlyButtonProps = {
  type:'iconOnly'
  icon:React.ReactNode;
  onClick:()=>void;
}

type IconButtonProps = {
  type:'icon'
  icon:React.ReactNode;
  label:string;
  onClick:()=>void;
}

type ButtonWrapperProps = TextButtonProps | IconOnlyButtonProps | IconButtonProps;

export const ButtonContainer = (props: ButtonWrapperProps) => {
  const renderButton = () => {
      switch (props.type) {
          case 'text':
              return (
                  <Button onClick={props.onClick}>{props.label}  </Button>
              );

          case 'iconOnly':
              return (
                   <IconButton onClick={props.onClick}>
                     {props.icon}
                   </IconButton>
              );

          case 'icon':
              return (
                   <Button startIcon={props.icon}>
                     {props.label}
                   </Button>
              );
      }
  };
  return <>{renderButton()}</>;
};
© www.soinside.com 2019 - 2024. All rights reserved.