通过 React 高阶组件传递子道具的正确 TypeScript 类型

Posted

技术标签:

【中文标题】通过 React 高阶组件传递子道具的正确 TypeScript 类型【英文标题】:Correct TypeScript types for passing children props through a React higher order component 【发布时间】:2021-11-23 15:02:51 【问题描述】:

考虑以下代码,其中包含一个高阶组件、一个函数式组件以及一个使用 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);

但是,当我们尝试使用这个新的WrappedComponent

return (
  <WrappedComponent>
    <h1>Hello</h1>
    <h2>World</h2>
  </WrappedComponent>
);

我们最终得到错误:Type ' children: Element[]; ' has no properties in common with type 'IntrinsicAttributes &amp; InjectedProps'.

这可以通过将children props 注入到 HOC 的 props 中来解决,像这样;

interface InjectedProps 
  someProp?: number;
  children?: React.ReactNode;

然而,我们现在遇到的问题是所有包装的组件现在都可以接收子组件,即使它们以前不能。

我的问题是,对于将子组件传递到包装组件中的高阶组件,正确的类型是什么?

【问题讨论】:

【参考方案1】:

你看到这个错误是因为P extends ,而它应该扩展P extends children?: React.ReactNode; ,因为你想提供children

顺便说一句,仅使用空对象 作为通用约束被认为是一种不好的做法。您应该使用Record&lt;PropertyKey, unknown&gt; 而不是

此外,您应该使用ComponentType&lt;Omit&lt;P &amp; InjectedProps, "someProp"&gt;&gt; 而不是ComponentType&lt;P&gt;,因为这是 TS 推断此类型的方式。

工作代码:

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>
)

Playground

【讨论】:

以上是关于通过 React 高阶组件传递子道具的正确 TypeScript 类型的主要内容,如果未能解决你的问题,请参考以下文章

高阶组件中功能组件的道具

反应:子组件未接收通过“this.state”传递的道具

在 react-router v4 中将自定义道具传递给路由器组件

在 react-router v4 中将自定义道具传递给路由器组件

在 React 的子组件中将状态作为道具传递

高阶组件状态正在正确更新,但接收道具的包装组件不会在状态更改时重新渲染