你好,我遇到了这样的情况,我想通过它的 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 为什么? 打字稿游乐场
在您的情况下,您可以简单地使用歧视联合,而不是链接的条件类型:
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 */}
</>