打字稿:联合型零件道具的HOC道具类型

时间:2020-05-10 17:27:04

标签: reactjs typescript

我的prop组件如下:

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'.

如何获得理想的结果?

1 个答案:

答案 0 :(得分: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
    }
  };
}

已按照上面显示的方式定义,您可以在App.tsx中使用它,而不会出现任何 TypeError

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<Props>(Comp); // LINE 1

  2. HOC的定义:我们将传递的接口接收到通用变量P中,传递的组件WrappedComponent声明其类型为 React ComponentType以P作为道具界面

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

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

    return <WrappedComponent {...(this.props as P)} />; // LINE 4

  4. 现在您可以看到P has -> setSelectedValue: (value: number | string) => voidProps has -> setSelectedValue: (value: number) => void,它们应作为 TypeError 抛出,我们通过避免了输入强制转换作为第4行。您可以尝试删除此强制转换,它将开始显示错误。

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