【问题标题】:How can I make a TypeScript interface prop depend on another prop within the same interface?如何使 TypeScript 界面道具依赖于同一界面中的另一个道具?
【发布时间】:2020-05-13 19:27:31
【问题描述】:
type ButtonVariant = 'action' | 'hero';

type Size = 'small' | 'medium' | 'large';

export interface ButtonProps {
    variant: ButtonVariant;
    size?: Size;
}

export default function Button(props: ButtonProps): ReactElement {
    const { variant } = props;

    if (variant === 'hero')) {
        return <HeroButton {...props} />;
    }

    if (variant === 'pill') {
        return <PillButton {...props} />;
    }
}

在上面的代码中,我有两个 React 按钮的变体:HeroButtonPillButton

两个按钮都期望“ButtonProps”作为它们的道具类型。但是,我想让 HeroButton only 期望大小为“中”或“大”。 PillButton 应该接受“小”、“中”或“大”作为其大小属性。

问题:我如何编写ButtonProps 接口,使得Button 组件允许(并在VS Code 中建议)'small' | 'medium' | 'large' 作为尺寸道具,当变量道具为“药丸”时",但只允许 'medium' | 'large' 变体道具是“英雄”?

注意:我已经研究过 TypeScript Discriminate Unions 来解决这个问题,但还没有成功。

【问题讨论】:

    标签: reactjs typescript


    【解决方案1】:

    试试这个:

    export interface HeroButtonProps {
        variant: 'hero';
        size?: 'medium' | 'large';
    }
    
    export interface PillButtonProps {
        variant: 'pill';
        size?: 'small' | 'medium' | 'large';
    }
    
    export type ButtonProps = HeroButtonProps | PillButtonProps;
    

    然后将HeroButton 更改为只接受HeroButtonPropsPillButton

    【讨论】:

      【解决方案2】:

      这样的东西应该可以工作

      type DiscUnion =
      | { variant: "hero"; size?: "medium" | "large" }
      | { variant: "pill"; size?: "small" | "medium" | "large" };
      
      export default function Button(props: DiscUnion): any {
          if (props.variant === "hero") {
              const w = props.size; //typeof w is "medium" | "large"
          }
      
          if (props.variant === "pill") {
              const w = props.size; //typeof w is "small" | "medium" | "large"
          }
      }
      
      // allowed
      Button({ variant: "hero", size: "medium" });
      
      // not allowed
      Button({ variant: "hero", size: "small" });
      

      请注意,我们不会对变体进行解构,这样做会使您失去控制流分析,https://github.com/microsoft/TypeScript/issues/9998

      编辑 - 这是一个游乐场链接https://www.typescriptlang.org/play/?jsx=2#code/JYWwDg9gTgLgBAJQKYEMDG8BmUIjgcilQ3wG4BYAKFEljgG9FiYBRAGyRCQDt4BfONlxwAREXQwRFSlRgBPMEjgARYAGc0AVW7AI3OAF4qAHwZwAbiijAUvAFyiAFkhxS4a4AC8kAfgciuABNgAFcQEThTETYrAHMkCL4qOBTIs0trWxh-MGA2NjcPbz9RNRAUfIiooNDwtOi4hLg+aSpMEO4MXX0ACRcIACEQmBg9AAowHDA1B1s5AEoHZAl2Th54emTUohgQqH0AHmDzAD5HYAOAemOTqiSZSnbOmG64AAU8tiGR8cmIadm3AWS2Yqy4vAYWxSOz2hxuACM5Egrjc7lQqEgAB60eCBJCYFAhNhYDpdPRwb6jbgTKYzFTqLQ6PSLJgrDjgjZQuBoPRqeCeQxwP7TAB0GRsvC5agA7sAYGhHHAaf81GKrBKYPNIZRUrruSg1EoRM5XA5Njq9Zaedw+XBpYLhaqikhSHBLpd5IoIJg7XB1KIamEqqIYlB4iIuZboUhdvs4Ac+jhKeT6CK046BJdbhbLfco-rDaJcpVtfnddbbfaDELaSLna73Z6kN7ff6RGUKgV6oG6lFQ+HI1GYXGDh98sn9Kn07TM9n83nUvd7ubdQcJxZ1VkDMb+hFnduexEs2jKCvUmvhlSN5leNuTRA914kNuOyXj5R7kA

      【讨论】:

      • 这消除了我的编译器错误。但是,当使用&lt;Button variant="hero" size="small" /&gt; 时,我现在在 VS Code 中没有收到任何警告。 “variant”道具提供了允许的值作为建议(“hero”|“pill”),但在使用“size”道具时我没有得到任何建议或更正。这是在 TS 中使用可区分联合的正常副作用吗?
      • 不,这听起来不典型,我在上面添加了一个链接到您的用例,如果这在您的 vs 代码中不起作用,那么可能是打字稿版本或反应问题?
      猜你喜欢
      • 2019-07-15
      • 1970-01-01
      • 1970-01-01
      • 2020-10-20
      • 2023-01-28
      • 2019-03-05
      • 1970-01-01
      • 2021-09-26
      • 1970-01-01
      相关资源
      最近更新 更多