什么是TypeScript HOC用作装饰器的正确返回类型?

时间:2018-06-10 13:34:29

标签: reactjs typescript higher-order-components

我试图在TypeScript中编写一个简单的HOC,并且对返回类型应该是什么感到困惑。 HOC看起来像这样:

export const requiresUser = <P extends object>(Component: React.ComponentType<P>) =>
  class RequiresUser extends React.Component<P> {
    componentDidMount() {
      console.log("requires user")
    }

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

如果我在这样的组件中使用它:

@requiresUser
export class DashboardPage extends React.Component<{}> {

  someFunction = () => {
    console.log("hi")
  }

  render() {
    return (
      <div>
        DashboardPage
      </div>
    )
  }
}

由于someFunction函数,编译器很难过。如果我删除了这个功能,那就太酷了,因为我觉得这一切都很好地匹配,而不必明确地设置任何东西。以下是组件包含someFunction时的错误:

(11, 1): Unable to resolve signature of class decorator when called as an expression.
  Type 'typeof RequiresUser' is not assignable to type 'typeof DashboardPage'.
    Type 'requiresUser<{}>.RequiresUser' is not assignable to type 'DashboardPage'.
      Property 'someFunction' is missing in type 'requiresUser<{}>.RequiresUser'.

所以我的问题是,HOC的返回类型应该允许哪些组件使用它来定义他们想要的任何功能?返回any会使其有效,但感觉就像在作弊..

1 个答案:

答案 0 :(得分:1)

好像typescript现在不支持装饰器中的类型突变(因为装饰的组件与原始组件不同)。

https://github.com/Microsoft/TypeScript/issues/4881

解决方法:

export const requiresUser = <
  P,
  T extends { new (props: P): React.Component<P> }
>(
  Component: T
): T => {
  class RequiresUser extends React.Component<P> {
    componentDidMount() {
      console.log("requires user");
    }

    render() {
      return <Component {...this.props} />;
    }
  }
  return RequiresUser as T;
};