这是一个通过函数推断来推断C 和P 的类型的技巧。通常,类型参数只是推断的形式参数,而不是来自其他类型参数。所以即使我们在P 和C (P extends RouteComponentProps<any>, C extends React.ComponentType<P>) 之间有关系,P 也不会根据C 推断出来
function X(p: RouteComponentProps<{ p: string }>){
return null!
}
export declare function withRouter<P extends RouteComponentProps<any>, C extends React.ComponentType<P>>(
component: C
): React.ComponentClass<Omit<P, keyof RouteComponentProps<any>> & WithRouterProps<C>> & WithRouterStatics<C>;
let x2 = withRouter(X) // P is RouteComponentProps<any>
Playground Link
现在,如果参数属于交集类型,则该参数的参数将用作交集中两种类型的推理站点。因此,当我们有C & React.ComponentType<P> 时,参数X 将用于推断React.ComponentType<P> 中的C 和P。
export declare function withRouter<P extends RouteComponentProps<any>, C extends React.ComponentType<P>>(
component: C & React.ComponentType<P>
): React.ComponentClass<Omit<P, keyof RouteComponentProps<any>> & WithRouterProps<C>> & WithRouterStatics<C>;
let x2 = withRouter(X) // P is { p: string }
Playground Link
请注意,在 TS 的较新版本中,我们可以使用条件类型从 C 中提取 P,而无需使用交集技巧(尽管这里可能存在 2.8 之前的兼容约束,或者我可能没有的性能约束意识到)。所以我们可以将 HOC 重写为:
export declare function withRouter<C extends React.ComponentType<RouteComponentProps<any>>>(
component: C
): React.ComponentClass<Omit<React.ComponentProps<C>, keyof RouteComponentProps<any>> & WithRouterProps<C>> & WithRouterStatics<C>;
let x2 = withRouter(X) // P is { p: string }
React.ComponentProps是react中定义的条件类型。
Playground Link