Reactjs 允许无状态函数接受多个不同的prop接口

Reactjs 允许无状态函数接受多个不同的prop接口,reactjs,typescript,Reactjs,Typescript,如何允许函数接受多个不同的prop接口?在下面的示例中,我希望它接受IFlatProps或IChildrenProps。我尝试了下面的方法,但似乎不起作用: const Field: React.SFC<IFlatProps | IChildrenProps> = ({ label, name, helpText, children }) => ( // ... ); 编辑:我从typescript得到的错误是: [ts]类型“(IFlatProps&{childre

如何允许函数接受多个不同的prop接口?在下面的示例中,我希望它接受
IFlatProps
IChildrenProps
。我尝试了下面的方法,但似乎不起作用:

const Field: React.SFC<IFlatProps | IChildrenProps> = ({
  label, name, helpText, children
}) => (
  // ...
);
编辑:我从typescript得到的错误是:

[ts]类型“(IFlatProps&{children?:ReactNode;})|(IChildrenProps &{children?:ReactNode;})'没有属性'label'和字符串 索引签名

这个错误是针对
标签
属性的,我还针对
名称
属性得到了相同的错误


这里有一个代码沙盒复制了这个问题:

问题是,根据定义,您只能访问联合类型的公共字段,并且由于某些字段在两个接口之间不是公共字段,您无法访问它们,因此也无法对其进行分解。最简单的解决方案是将
const
作为
SFC
键入,但将函数的参数键入可以选择包含所有联合成员的对象,如
Partial

const字段:React.SFC=({
标签、名称、帮助文本、子项//全部按原始类型键入|未定义
}:部分)=>(
无效的
);

对于您的情况,这是很好的,因为没有常见的强制属性,所以我们可以将所有属性视为参数上的可选参数。如果我们有这样的属性,我们可以使用更复杂的类型来保持这样一个事实,即这样的属性应该始终存在

const Field: React.SFC<IFlatProps | IChildrenProps> = ({
    label, name, helpText, children, //these are still optional 
    commonNotOptional //will be just string 
}: Merge<IFlatProps, IChildrenProps>) =>  null;

type Merge<T1, T2> = Pick<T1, Extract<keyof T1, keyof T2>> &
    Pick<T2, Extract<keyof T2, keyof T1>> &
    Partial<T1 & T2>

interface IFlatProps {
    label: string;
    name: string;
    commonNotOptional: string
    helpText?: string | JSX.Element;
}

interface IChildrenProps {
    children: React.ReactNode;
    helpText?: string | JSX.Element;
    commonNotOptional: string

}
const字段:React.SFC=({
标签、名称、帮助文本、子项,//这些仍然是可选的
commonNotOptional//将只是字符串
}:Merge)=>null;
类型Merge=Pick&
挑&
部分的
接口IFlatProps{
标签:字符串;
名称:字符串;
commonNotOptional:字符串
helpText?:字符串| JSX.Element;
}
接口IChildrenProps{
子节点:React.ReactNode;
helpText?:字符串| JSX.Element;
commonNotOptional:字符串
}

如果您将它们合并会怎么样<代码>键入IFlatOrChildrenprops=IFlatProps | IChildrenProps然后
React.SFC
。我不确定这是否会奏效,因此我没有将其作为aswer发布。请让我know@MatthewBarbara不,这似乎与我上面的代码完全相同。添加了我要回答的具体错误。谢谢。我现在看到的问题是,当定义了
子项时,编译器仍然认为
名称
标签
可以
未定义
。这导致我看到错误
类型“undefined”不能用作索引类型。
在我的函数中使用
name
时。演示:@DaveJ编译器就在这里。由于道具是
IFlatProps
IChildrenProps
名称可能未定义,因为它在
IChildrenProps
中不作为必填字段存在。您应该在使用它的地方为它提供一个默认值
name | |“default”
Yes,但是该代码是不可访问的,因为它由一个检查来保护,以查看是否定义了
子项。这似乎不是一种很好的方法(
name | |“default”
),因为
“default”
没有任何意义,只是一个用来编译它的转义图案填充。也许我的想法是错误的,因为我只使用了一周的Typescript。。。关于我如何写这篇文章,你还有其他想法吗?也许一个包装器函数同时接受两种类型的道具和两个子函数,而这两个子函数只接受
IFlatProps
IChildrenProps
?@DaveJ是的,最简单的解决方案可能是拥有两个函数,并使用自定义类型的防护。在您提供的示例中,您使用的是旧版本的TS。在2.9中,我们可以在
类型中使用一个
。@DaveJ确定:
const Field: React.SFC<IFlatProps | IChildrenProps> = ({
     label, name, helpText, children // All typed as original type |undefined 
}: Partial<IFlatProps & IChildrenProps>) => (
    null
);
const Field: React.SFC<IFlatProps | IChildrenProps> = ({
    label, name, helpText, children, //these are still optional 
    commonNotOptional //will be just string 
}: Merge<IFlatProps, IChildrenProps>) =>  null;

type Merge<T1, T2> = Pick<T1, Extract<keyof T1, keyof T2>> &
    Pick<T2, Extract<keyof T2, keyof T1>> &
    Partial<T1 & T2>

interface IFlatProps {
    label: string;
    name: string;
    commonNotOptional: string
    helpText?: string | JSX.Element;
}

interface IChildrenProps {
    children: React.ReactNode;
    helpText?: string | JSX.Element;
    commonNotOptional: string

}