Typescript `typeof React.Component` 不扩展接口?无法定义高阶组件

IT技术 reactjs typescript higher-order-components
2021-04-27 23:51:59

我正在创建一个高阶组件来包装扩展接口的组件:

interface ClickOutsideInterface {
  onClickOutside: (e: Event) => void
}

我创建的工厂期望React.ComponentClass实现ClickOutsideInterface

  function clickOutside<P>(Component: React.ComponentClass<P> & ClickOutsideInterface){    
    return class ClickOutside extends React.Component<P, {}> { 
      /* on click outside invoke Component.onClickOutside  */

      render() {
        return(<div><Component {...this.props} /></div>)
      }
   }
}

为了测试工厂,我实现了一个扩展 ClickOutsideInterface

class Test extends React.Component<TProps, TState> implements ClickOutsideInterface {
  onClickOutside(event: Event): void {
    this.setState({
      closed: true
    })
  }

  render(){
    return(
      <div>{this.state.closed}</div>
    )
  }
}

但是当我在函数中使用组件作为参数时clickOutside

const withClickOutside = clickOutside(Test)

我收到以下参数类型错误Test

“typeof Test”类型的参数不可分配给“ComponentClass & ClickOutsideInterface”类型的参数。类型“typeof Test”不可分配给类型“ClickOutsideInterface”。“typeof Test”类型中缺少“onClickOutside”属性。

有什么想法为什么 Typescript 认为我没有在Test.

1个回答

TypeScript 说你还没有实现你的函数需要它的参数的接口,因为你确实没有。

当你写

class A {
  //...
}

您定义两种类型和一种值。

名为A是类。它是您调用new以创建对象的函数

第一种类型,也称为A,是通过调用类函数创建的对象的类型,new如上所述。

第二种类型是该类函数的类型。声明一个类不会自动为此类型创建名称,但该类型仍然存在,因为所有值都有一个类型。写这个类型是typeof A因为它是值A的类型,是类的类型。

因此,根据您要完成的工作,您需要要么

传递一个实例 Test

const withClickOutside = clickOutside(new Test);

或者更改您的函数,以便它采用与类本身的类型匹配的对象,而不是它创建的对象

function clickOutside<P>(
  Component: new () => React.ComponentClass<P> & ClickOutsideInterface
) {...}

我怀疑在这种情况下你想要的是后者。

最后,虽然您可能希望它用于完全有效的文档目的,但我想指出,实际上没有理由声明您的类甚至根本实现了接口。TypeScript 是一种结构类型化语言,所有接口都是通过具有兼容的成员实现的。