【问题标题】:Typescript `typeof React.Component` does not extend interface? Trouble defining higher-order componentTypescript`typeof React.Component`不扩展接口?难以定义高阶组件
【发布时间】:2017-10-29 15:14:37
【问题描述】:

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

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”类型的参数不能分配给类型参数 “组件类和 ClickOutsideInterface”。类型'typeof Test'是 不可分配给类型“ClickOutsideInterface”。 “typeof Test”类型中缺少属性“onClickOutside”。

任何想法为什么 Typescript 认为我没有在 Test 中实现接口?

【问题讨论】:

  • 不是装饰器? withClickOutside()(Test)
  • 可能是的:)
  • @DmitriyKovalenko 装饰器与否,如果此函数是装饰器,您建议的调用将不正确,因为它是装饰器工厂调用而不是装饰器调用。仅当clickOutside 返回一个可用作装饰器的函数时才有效。无论如何,这在这里没有意义,因为它不需要任何参数。

标签: reactjs typescript higher-order-components


【解决方案1】:

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

当你写作时

class A {
  //...
}

你定义了两种类型和一个值。

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

第一个type,也被命名为A,是如上所述通过new调用类函数创建的对象的类型.

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

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

传递Test的实例

const withClickOutside = clickOutside(new Test);

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

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

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

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

【讨论】:

  • 感谢阿伦!正如您所推荐的,我能够通过使用 `Component: new(props: P) => React.Component

    & ClickOutsideInterface` 来让它工作,谢谢!我希望能够在 HO 组件中引用 React.ComponentClass displayNameClickOustideInterface 上公开的方法,例如 Component.onClickOutside - 有没有办法访问函数 Component 的返回类型?类似Component: new(props: P) =&gt; (C: React.Component&lt;P&gt; &amp; ClickOutsideInterface)

  • @tgk 是类的那些静态成员吗​​?
  • 您可以使用您提到的语法使其采用您喜欢的任何收缩器参数
  • 不,不幸的是它们不是类的静态成员——我需要以某种方式重组我的工厂以访问实例。
猜你喜欢
  • 2018-05-26
  • 1970-01-01
  • 1970-01-01
  • 2022-12-06
  • 1970-01-01
  • 2020-10-30
  • 2020-06-09
  • 2016-07-06
  • 2017-10-21
相关资源
最近更新 更多