首頁  >  問答  >  主體

基於其他 props,使 React props 在 TypeScript 中成為可選且必要的

我有一個React按鈕容器元件,根據使用者使用的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 prop是可選的,因為它只用於帶有圖示的圖示按鈕和常規按鈕。我希望只有當從ButtonContainer傳遞的類型為text時,icon prop才是可選的;如果傳遞給ButtonContainer的類型是icon或iconOnly,則它應該是一個必需的prop。

P粉738046172P粉738046172419 天前664

全部回覆(1)我來回復

  • P粉803444331

    P粉8034443312023-09-18 12:22:20

    我會選擇使用來辨別聯合類型

    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()}</>;
    };
    

    回覆
    0
  • 取消回覆