2

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

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

4

1 回答 1

4

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

当你写

class A {
  //...
}

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

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

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

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

因此,根据您要完成的任务,您需要

传递一个实例Test

const withClickOutside = clickOutside(new Test);

或者改变你的函数,让它接受一个与类本身类型匹配的对象,而不是它创建的对象

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

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

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

于 2017-10-29T16:35:00.447 回答