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

时间:2018-07-01 11:35:14

标签: reactjs typescript

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

const Field: React.SFC<IFlatProps | IChildrenProps> = ({
  label, name, helpText, children
}) => (
  // ...
);

界面如下:

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

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

编辑:我从打字稿中得到的错误是:

  

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

此错误是由于label属性引起的,我也遇到了与name属性有关的错误。

这是一个复制问题的代码框:https://codesandbox.io/s/k5o20kvo4o

1 个答案:

答案 0 :(得分:1)

问题在于,根据定义,您只能访问并集类型的公共字段,并且由于某些字段在两个接口之间不通用,因此您无法访问它们,因此也无法对它们进行解构。最简单的解决方案是将const键入为SFC<IFlatProps|IChildrenProps>,但是将函数的参数键入具有可选的所有联合成员的对象,例如Partial<IFlatProps & IChildrenProps>

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

}