首页 > 解决方案 > 用作装饰器的 TypeScript HOC 的正确返回类型是什么?

问题描述

我正在尝试在 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让它工作,但感觉像作弊..

标签: reactjstypescripthigher-order-components

解决方案


似乎打字稿现在不支持装饰器中的类型突变(因为装饰的组件与原始组件不同)。

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;
};

推荐阅读