TypeScript不从React.ComponentType推断道具

时间:2019-06-13 15:52:16

标签: reactjs typescript generics

我具有以下功能,我想使用该功能接收ComponentType及其道具,以便允许我将这些道具与RouteComponentProps一起注入

const routeComponentFactory = <TProps extends {}>(
    Component: React.ComponentType<TProps>,
    props: TProps
) => {
    return (routeProps: RouteComponentProps) => {
        return <Component {...routeProps} {...props} />;
    };
};

如果我明确指定TProps,则此函数可以正常工作,例如:

interface MyComponentProps { a: number; b: number; }
const MyComponent: React.FunctionComponent<MyComponentProps> = () => null;

routeComponentFactory<MyComponentProps>(MyComponent, {});

由于在对象中未提供ab而出现错误。

但是,如果删除显式的<MyComponentProps>,错误就会消失,并且可以使用空对象调用该函数。

如何使TypeScript正确推断MyComponentProps

2 个答案:

答案 0 :(得分:2)

如果启用strictFunctionTypes,则会收到错误消息:

Type 'FunctionComponent<MyComponentProps>' is not assignable to type 'FunctionComponent<{}>'.

TProps有两个可能的推理站点,参数Componentprops都包含类型参数TProps,因此,打字稿会尝试查找将使两个站点同时出现的类型快乐。因为如果TProps{},则参数{}和道具类型MyComponentProps都可以分配给它,打字稿会推断TProps{}为了让大家开心。

strictFunctionTypes下确实出错的原因是,默认情况下,函数类型的行为是双变量的(因此,函数(p: MyComponentProps) => JSX.Element可分配给(p: {}) => JSX.Element)。在strictFunctionTypes下,函数类型的行为相反,因此不允许进行此类分配。

即使没有strictFunctionTypes也会出错的解决方案是降低props推理站点的优先级,因此编译器会选择对Component有好处的东西,并与{{ 1}}。可以使用与props的交集来完成:

{}

答案 1 :(得分:1)

我看不到它允许我用一个空对象调用该函数,但是在我的情况下,它抱怨MyComponent属性无效。

看来问题在于它是从第二个参数推断类型的-我猜是因为它与最简单的类型匹配。

您可以这样定义您的函数,以强制其推断正确的类型:

const routeComponentFactory = <TProps extends {}>(
    Component: React.ComponentType<TProps>
) => (
    props: TProps
) => {
    return (routeProps: RouteComponentProps) => {
        return <Component {...routeProps} {...props} />;
    };
};

然后这样称呼它:

routeComponentFactory(MyComponent)({});

在这种情况下,它应该正确地抱怨空对象。