使用条件通用属性反应打字稿组件错误地推断类型

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

你好,我遇到了这样的情况,我想通过它的 prop 有条件地输入组件,但打字稿像往常一样与泛型一起工作很糟糕。你能解释一下为什么特别是组件打字稿工作不好,但如果我尝试创建一个变量 const test:Props<{variant:"link"}> ,它会正确推断类型?

import React from 'react';

type BaseProps = {
  variant: 'close' | 'link' | 'dropdown';
  text: string;
};

type CloseButtonProps = BaseProps & {
  onClose: () => void;
  onClick: () => void;
};

type LinkButtonProps = BaseProps & {
  href: string;
  isExternal?: boolean;
};

type DropdownButtonProps = BaseProps & {
  content: string;
};

type Props<T extends BaseProps> = T['variant'] extends 'close'
  ? CloseButtonProps
  : T['variant'] extends 'link'
    ? LinkButtonProps
    : DropdownButtonProps;

const MenuItem = <T extends BaseProps>(props: Props<T>) => {
  return null;
};

const element=<MenuItem variant="link" href="test" text="test"/>

如你所见,元素不能有 href 属性,因为它属于 DropdownProps 为什么? 打字稿游乐场

reactjs typescript
1个回答
0
投票

在您的情况下,您可以简单地使用歧视联合,而不是链接的条件类型

type BaseProps = {
  text: string;
};

type CloseButtonProps = BaseProps & {
  variant: 'close'; // Discrimant property with a unique literal value type in each member of the Union
  onClose: () => void;
  onClick: () => void;
};

type LinkButtonProps = BaseProps & {
  variant: 'link';
  href: string;
  isExternal?: boolean;
};

type DropdownButtonProps = BaseProps & {
  variant: 'dropdown';
  content: string;
};

您现在可以直接使用 Union,而无需诉诸类型推断:

const MenuItem = (props: CloseButtonProps | LinkButtonProps | DropdownButtonProps) => {
  return null;
};

<>
  <MenuItem variant="link" href="test" text="test" />{/* Okay */}
  <MenuItem variant="dropdown" href="test" content="foo" text="test" />{/* Property 'href' does not exist on type 'IntrinsicAttributes & BaseProps & { variant: "dropdown"; content: string; }'. */}
  {/*                          ~~~~ */}
  <MenuItem variant="dropdown" content="foo" text="test" />{/* Okay */}
</>

游乐场链接

© www.soinside.com 2019 - 2024. All rights reserved.