我具有以下功能,我想使用该功能接收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, {});
由于在对象中未提供a
和b
而出现错误。
但是,如果删除显式的<MyComponentProps>
,错误就会消失,并且可以使用空对象调用该函数。
如何使TypeScript正确推断MyComponentProps
?
答案 0 :(得分:2)
如果启用strictFunctionTypes
,则会收到错误消息:
Type 'FunctionComponent<MyComponentProps>' is not assignable to type 'FunctionComponent<{}>'.
TProps
有两个可能的推理站点,参数Component
和props
都包含类型参数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)({});
在这种情况下,它应该正确地抱怨空对象。