如何从高阶组件的const变量中声明通用React组件?

时间:2018-10-10 13:30:03

标签: reactjs typescript jsx

我有如下的TypeScript代码:

interface Props<T> {}

function HOC<P>(component: React.ComponentType<P>): React.ComponentType<P> {
  return component;
}

const MyClass = HOC(class MyClass<T> extends React.Component<Props<T>, {}> {});
type MyClass<T> = React.ComponentType<Props<T>>;

function render() {
  return <MyClass<string> />;
}

但这不起作用,因为我在MyClass<string>的行上遇到以下错误:

[ts]
JSX element type 'ReactElement<any> | null' is not a constructor function for JSX elements.
  Type 'null' is not assignable to type 'ElementClass'.
[ts] Expected 0 type arguments, but got 1.

如果我删除了HOC和类型声明,则可以正常编译:

interface Props<T> {}

class MyClass<T> extends React.Component<Props<T>, {}> {};

function render() {
  return <MyClass<string> />;
}

所以我的问题是,假设我无法修改HOC的类型声明,那么如何声明const MyClass(必要时使用type MyClass<T>),使得第一个示例将成功编译?

1 个答案:

答案 0 :(得分:3)

由于MyClass是通用构造函数,因此您将需要使用类型断言来让打字稿编译器:

interface Props<T> {
  prop: T
}

function HOC<P>(component: React.ComponentType<P>): React.ComponentType<P> {
  return component;
}

const MyClass = HOC(class MyClass<T> extends React.Component<Props<T>, {}> {}) as {
  new <T>(props: Props<T>, context?: any): React.Component<Props<T>> // Generic constructor
}

function render() {
  return <MyClass<string> prop="" />;
}

function render2() {
  return <MyClass<number> prop={1} />;
}

注意,据我所知,即使您可以更改HOC,不幸的是,打字稿也无法对您正在寻找的通用类型转换进行建模。