【问题标题】:Typescript: HOC prop type for union type component propTypescript:联合类型组件道具的 HOC 道具类型
【发布时间】:2026-02-08 04:35:01
【问题描述】:

我有像这样的道具的组件:

setSelectedValue: (value: number | string) => void;

我想做 HOC,它有 setSelectedValue 道具,只能传递数字,也可以作为道具传递给原始组件,我看到它的类型是这样的:

setSelectedValue: (value: number) => void;

当我尝试制作它时,我收到 TS 错误消息:

Type '(value: number) => void' is not assignable to type '(value: number | string) => void'.

我怎样才能得到想要的结果?

【问题讨论】:

    标签: reactjs typescript


    【解决方案1】:

    假设您的组件 (comp.tsx):

    import React from 'react';
    import hocComp from './hocComp';
    
    interface Props {
      setSelectedValue: (value: number | string) => void; // number | string
    }
    
    class Comp extends React.Component<Props> {
      render() {
        return <div>Comp</div>;
      }
    }
    
    export default hocComp<Props>(Comp); // LINE 1
    

    和 HOC (hocComp.tsx):

    import React from 'react';
    
    interface Props {
      setSelectedValue: (value: number) => void; // number // LINE 2
    }
    
    export default function hocComp<P extends object>(
      WrappedComponent: React.ComponentType<P>
    ) {
      return class extends React.Component<Props> {  // LINE 3  
        render() {
          return <WrappedComponent {...this.props as P} />; // LINE 4
        }
      };
    }
    

    按照上面显示的方式定义,你可以在没有任何TypeError的情况下使用它(在App.tsx中):

    import React from 'react';
    import Comp from './comp';
    
    export default function App() {
      function setSelectedValue(value: number) {
        console.debug(value);
      }
    
      return (
        <div className="App">
          <h1>Hello World</h1>
          <Comp setSelectedValue={setSelectedValue} />
        </div>
      );
    }
    

    这里是CodeSandbox


    这里有一个解释:

    1. 在调用 HOC 时我们将 component 及其 Props 接口传递到 HOC。

      export default withComp&lt;Props&gt;(Comp); // LINE 1

    2. HOC 的定义:我们接收到泛型变量P 的传递接口,并且传递的组件WrappedComponent 声明其类型为React ComponentType 与P 作为props 接口强>

      export default function withComp<P extends object>( WrappedComponent: React.ComponentType<P> ) {

    3. 最后,在 HOC 的内部渲染:我们调用传递的组件 WrappedComponent 并传递给它所有的 props,其接口定义如HOC 本身(第 2 行)-(请注意,这些道具在 HOC 返回的类中使用-第 3 行)

      return &lt;WrappedComponent {...(this.props as P)} /&gt;; // LINE 4

    4. 现在你可以看到P has -&gt; setSelectedValue: (value: number | string) =&gt; voidProps has -&gt; setSelectedValue: (value: number) =&gt; void 应该抛出 TypeError,我们通过 Type Casting 避免了这种情况strong> 为 LINE 4。您可以尝试删除此类型转换,它会开始显示错误。

    您还可以查看 this 帖子以了解 TypeScript 中的泛型

    【讨论】:

    • 谢谢!这就是我要找的!我想知道,如果我想为这个组件创建 Container 怎么办?如果您能帮助我了解如何做,我将不胜感激。
    • 我的第一个建议是使用泛型,但我坚持下去了
    • 是的,太好了!
    • 非常感谢!
    最近更新 更多