React HOC 类型推断
React HOC type inferring
我想创建a higher-order function that returns a higher-order component。
在下面的示例中,我创建了一个 validateSearchParams
函数,该函数创建了一个 函数 ,然后可用于包装组件。但是,Typescript (3.7.2) 无法正确推断类型。
export function validateSearchParams<Props extends { location: Location }>(
test: (searchParams: URLSearchParams) => boolean,
redirectTo: string,
): (Cmp: React.ComponentType<Props>) => React.ComponentType<Props> {
return (Cmp) => (props) => {
const searchParams = new URLSearchParams(props.location.search);
if (!test(searchParams)) {
return <Redirect to={redirectTo} />;
}
return <Cmp {...props} />;
};
}
export const Test: React.FC<{ something: boolean; location: Location }> = () => null;
// This is OK
validateSearchParams<{ something: boolean; location: Location }>(
(searchParams) => !!searchParams.get('foo'),
'hxxp://somewhere',
)(Test);
// ...but without an explicit type it does not compile
validateSearchParams((searchParams) => !!searchParams.get('foo'), 'http://test.example')(Test);
^^^^
在最后一行出现以下错误:
Argument of type 'FC<{ something: boolean; location: Location; }>' is not assignable to
parameter of type 'ComponentType<{ location: Location; }>'.
Type 'FC<{ something: boolean; location: Location; }>' is not assignable to type
'FunctionComponent<{ location: Location; }>'.
Types of parameters 'props' and 'props' are incompatible.
Type 'PropsWithChildren<{ location: Location; }>' is not assignable to type
'PropsWithChildren<{ something: boolean; location: Location; }>'.
Property 'something' is missing in type 'PropsWithChildren<{ location: Location; }>' but
required in type '{ something: boolean; location: Location; }'.ts(2345)
我还可以通过将 Cmp
合并到参数列表中来创建更简单的 HOC 版本:
export function validateSearchParams2<Props extends { location: Location; match: match<any> }>(
Cmp: React.ComponentType<Props>,
test: (searchParams: URLSearchParams) => boolean,
redirectTo: string,
): React.ComponentType<Props> {
return (props) => {
const searchParams = new URLSearchParams(props.location.search);
if (!test(searchParams)) {
return <Redirect to={redirectTo} />;
}
return <Cmp {...props} />;
};
}
export const Test: React.FC<{ something: boolean; location: Location }> = () => null;
validateSearchParams2(Test, (searchParams) => !!searchParams.get('foo'), 'hxxp://somewhere');
...但是有没有办法让 validateSearchParams
的第一个版本在没有显式类型的情况下工作?
现在在函数 validateSearchParams
上设置了通用类型 Props
。您想要将泛型移动到返回的函数。基本上 validateSearchParams
不是 通用函数,但它 returns 是通用 HOC。
export function validateSearchParams(
test: (searchParams: URLSearchParams) => boolean,
redirectTo: string,
): <Props extends { location: Location }>(Cmp: React.ComponentType<Props>) => React.ComponentType<Props> {
...
现在您不需要设置显式类型,因为它可以从您调用它的组件中推断出来。
我想创建a higher-order function that returns a higher-order component。
在下面的示例中,我创建了一个 validateSearchParams
函数,该函数创建了一个 函数 ,然后可用于包装组件。但是,Typescript (3.7.2) 无法正确推断类型。
export function validateSearchParams<Props extends { location: Location }>(
test: (searchParams: URLSearchParams) => boolean,
redirectTo: string,
): (Cmp: React.ComponentType<Props>) => React.ComponentType<Props> {
return (Cmp) => (props) => {
const searchParams = new URLSearchParams(props.location.search);
if (!test(searchParams)) {
return <Redirect to={redirectTo} />;
}
return <Cmp {...props} />;
};
}
export const Test: React.FC<{ something: boolean; location: Location }> = () => null;
// This is OK
validateSearchParams<{ something: boolean; location: Location }>(
(searchParams) => !!searchParams.get('foo'),
'hxxp://somewhere',
)(Test);
// ...but without an explicit type it does not compile
validateSearchParams((searchParams) => !!searchParams.get('foo'), 'http://test.example')(Test);
^^^^
在最后一行出现以下错误:
Argument of type 'FC<{ something: boolean; location: Location; }>' is not assignable to
parameter of type 'ComponentType<{ location: Location; }>'.
Type 'FC<{ something: boolean; location: Location; }>' is not assignable to type
'FunctionComponent<{ location: Location; }>'.
Types of parameters 'props' and 'props' are incompatible.
Type 'PropsWithChildren<{ location: Location; }>' is not assignable to type
'PropsWithChildren<{ something: boolean; location: Location; }>'.
Property 'something' is missing in type 'PropsWithChildren<{ location: Location; }>' but
required in type '{ something: boolean; location: Location; }'.ts(2345)
我还可以通过将 Cmp
合并到参数列表中来创建更简单的 HOC 版本:
export function validateSearchParams2<Props extends { location: Location; match: match<any> }>(
Cmp: React.ComponentType<Props>,
test: (searchParams: URLSearchParams) => boolean,
redirectTo: string,
): React.ComponentType<Props> {
return (props) => {
const searchParams = new URLSearchParams(props.location.search);
if (!test(searchParams)) {
return <Redirect to={redirectTo} />;
}
return <Cmp {...props} />;
};
}
export const Test: React.FC<{ something: boolean; location: Location }> = () => null;
validateSearchParams2(Test, (searchParams) => !!searchParams.get('foo'), 'hxxp://somewhere');
...但是有没有办法让 validateSearchParams
的第一个版本在没有显式类型的情况下工作?
现在在函数 validateSearchParams
上设置了通用类型 Props
。您想要将泛型移动到返回的函数。基本上 validateSearchParams
不是 通用函数,但它 returns 是通用 HOC。
export function validateSearchParams(
test: (searchParams: URLSearchParams) => boolean,
redirectTo: string,
): <Props extends { location: Location }>(Cmp: React.ComponentType<Props>) => React.ComponentType<Props> {
...
现在您不需要设置显式类型,因为它可以从您调用它的组件中推断出来。