【问题标题】:Correct TypeScript types for passing children props through a React higher order component通过 React 高阶组件传递子道具的正确 TypeScript 类型
【发布时间】: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;
}

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

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

【问题讨论】:

    标签: reactjs typescript react-native type-inference typescript-generics


    【解决方案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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-25
      • 2019-06-26
      • 1970-01-01
      • 2020-11-09
      • 1970-01-01
      • 1970-01-01
      • 2020-09-10
      相关资源
      最近更新 更多