[英]Correct TypeScript types for passing children props through a React higher order component
Consider the following code, containing a higher order component, a functional component, and a component created using the HOC and our functional component:考虑以下代码,其中包含一个高阶组件、一个功能组件以及一个使用 HOC 和我们的功能组件创建的组件:
interface InjectedProps {
someProp?: number;
}
const myHoc = <P extends {}>(
Component: ComponentType<P>
) => ({someProp, ...props}: P & InjectedProps) => {
return <Component {...props as P} />;
}
const MyComponent = (props: {children?: React.ReactNode}) => {
return <div>{props.children}</div>;
};
const WrappedComponent = myHoc(MyComponent);
However, when we try and use this new WrappedComponent
:但是,当我们尝试使用这个新的
WrappedComponent
:
return (
<WrappedComponent>
<h1>Hello</h1>
<h2>World</h2>
</WrappedComponent>
);
We end up with the error: Type '{ children: Element[]; }' has no properties in common with type 'IntrinsicAttributes & InjectedProps'.
我们最终得到了错误:
Type '{ children: Element[]; }' has no properties in common with type 'IntrinsicAttributes & InjectedProps'.
Type '{ children: Element[]; }' has no properties in common with type 'IntrinsicAttributes & InjectedProps'.
. .
This can be solved by injecting the children
prop into the props of the HOC, like so;这可以通过将
children
prop 注入 HOC 的 props 来解决,像这样;
interface InjectedProps {
someProp?: number;
children?: React.ReactNode;
}
However, we now have the problem of all wrapped components can now take on children , even when they could previously not.然而,我们现在面临的问题是所有包装的组件现在都可以带子组件,即使它们以前不能。
My question is, what is the proper typing for a higher order component which passes down the children in the wrapped component?我的问题是,在包装组件中传递子代的高阶组件的正确类型是什么?
You see this error because P extends {}
, whereas it should extends P extends { children?: React.ReactNode; }
你看到这个错误是因为
P extends {}
,而它应该扩展P extends { children?: React.ReactNode; }
P extends { children?: React.ReactNode; }
because you want to provide children
. P extends { children?: React.ReactNode; }
因为你想提供children
。
Btw, it is considered a bad practice to use just empty object {}
as a generic constraint.顺便说一句,仅使用空对象
{}
作为通用约束被认为是一种不好的做法。 You should use Record<PropertyKey, unknown>
instead {}
.您应该使用
Record<PropertyKey, unknown>
代替{}
。
Also, you should use ComponentType<Omit<P & InjectedProps, "someProp">>
instead of ComponentType<P>
because this is how TS infers this type.此外,您应该使用
ComponentType<Omit<P & InjectedProps, "someProp">>
而不是ComponentType<P>
因为这是 TS 推断此类型的方式。
Working code:工作代码:
import React, { FC, ComponentType } from 'react'
interface InjectedProps {
someProp?: number;
}
type WithChildren = {
children?: React.ReactNode;
}
const myHoc = <P extends WithChildren>(
Component: ComponentType<Omit<P & InjectedProps, "someProp">>
) => ({ someProp, ...props }: P & InjectedProps) => <Component {...props} />
const MyComponent: FC = (props) => <div>{props.children}</div>
const WrappedComponent = myHoc(MyComponent);
const App = () => (
<WrappedComponent>
<h1>Hello</h1>
<h2>World</h2>
</WrappedComponent>
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.