【问题标题】:How to infer type correctly based on another type?如何根据另一种类型正确推断类型?
【发布时间】:2023-03-30 11:10:02
【问题描述】:

props.grouptrue时,我想将tab对象的类型推断为{leftText: string, rightText?: string}类型,当props.groupfalse时推断{title: string}类型。

type ButtonTab =
  | {
      leftText: string;
      rightText?: string;
    }
  | { title: string };

interface ButtonTabsProps {
  tabsList: ButtonTab[];
  group?: boolean;
}

function ButtonTabs(props: Readonly<ButtonTabsProps>) {
    return props.tabsList.map((tab: ButtonTab) => {
        if(props.group) {
            return `${tab.leftText} ${tab.rightText}`
        }
        return `${tab.title}`
    })
}

目前,TSC 抛出错误:

类型“ButtonTab”上不存在属性“leftText”。 类型 '{ title: string; 上不存在属性 'leftText' }'。

代码:TypeScript Playground

【问题讨论】:

  • 听起来您希望 ButtonTabsProps 成为联合类型,而不是 ButtonTab

标签: typescript typescript-typings


【解决方案1】:

在您的代码中,props.group 属性与 ButtonTab 类型无关。

props.group 应该搬出去了。

type ButtonTab<G extends boolean = true> = G extends true
  ? {
      leftText: string;
      rightText?: string;
    }
  : {title: string};

type ButtonTabsProps =
  | {
      tabsList: ButtonTab<true>[];
      group: true;
    }
  | {
      tabsList: ButtonTab<false>[];
      group: false;
    };

function ButtonTabs(props: ButtonTabsProps) {
  if (props.group) {
    return props.tabsList.map(tab => {
      return `${tab.leftText} ${tab.rightText}`;
    });
  }

  return props.tabsList.map(tab => {
    return `${tab.title}`;
  });
}

TS Playground

【讨论】:

    【解决方案2】:
    interface ButtonTabText {
      leftText: string
      rightText?: string
    }
    interface ButtonTabTitle {
      title: string
    }
    
    interface ButtonTabsText {
      group: true
      tabsList: ButtonTabText[]
    }
    interface ButtonTabsTitle {
      group: false
      tabsList: ButtonTabTitle[]
    }
    
    type Props = ButtonTabsTitle | ButtonTabsText
    
    const renderTabsText = (tabsList: ButtonTabText[]): string[] =>
      tabsList.map((tab) => `${tab.leftText} ${tab.rightText}`)
    
    const renderTabsTitle = (tabsList: ButtonTabTitle[]): string[] =>
      tabsList.map((tab) => tab.title)
    
    function ButtonTabs(props: Readonly<Props>) {
      return props.group
        ? renderTabsText(props.tabsList)
        : renderTabsTitle(props.tabsList)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-09
      • 2012-04-17
      • 1970-01-01
      • 2011-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多