基于其他 props,使 React props 在 TypeScript 中成为可选和必需的
P粉738046172
P粉738046172 2023-09-17 13:42:00
0
1
671

我有一个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粉738046172
P粉738046172

全部回复(1)
P粉803444331

我会选择使用辨别联合类型

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()}</>;
};
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板