React + Typescript 组件的类型

2,363 阅读1分钟

在使用React + Typescript开发高阶组件时,组件作为参数传入,代码如下: image.png

在上面的代码中,形参Component的类型是:
Component: React.Component<any, any>

在使用Component时,Typescript类型检查报错:
JSX element type 'Component' does not hav any constructor or call signatures

如下图所示: image.png

该报错的意思就是JSX元素Component的类型中缺少构造函数或调用签名,简而言之就是你丫类型写错了。

在编写React Component时,我们会按下面这种方式编写:

class Greeter extends React.Component<any, any> {
    render() {
        return <div>Hello, {this.props.whoToGreet}</div>;
    }
}

按下面的方式一使用:

return <Greeter whoToGreet='world' />;

但是,不能这么使用,方式二

let Greet = new Greeter();
return <Greet whoToGreet='world' />;

在方式一中,Greeter是作为一个constructor(构造函数)传递给我们的组件,这是正确的方式;但是在方式二中,Greet是作为一个instance(实例对象)传递给组件,这是错误,同时会报出一个运行时错误 ———— “Object is not a function”

因此,回到上文中的withHomeTopContextHOC函数

function withHomeTopContextHOC(Component: React.Component<any, any>) {
    return function HomeTopContextComponent(props: any) {
        return (
            <HomeTopContext.Consumer>
                {configUpdate => <Component {...props} configUpdate={configUpdate} />}
            <HomeTopContext.Consumer>
        )  
    }
}

形参期望的是React.Component的实例对象,但是我们传递给它的实参是返回React.Component的构造函数,而将其作为一个React组件使用时,也是将其作为一个构造函数使用的,也就是说,实参的类型和将其作为组件使用的方式没有错,只是形参的类型错误了,导致Typescript类型解析报错。

该函数所要表达的意思是:该函数接收一个React Component作为实参,因此,有以下几种方式来声明React Component的类型:

  1. Component: React.ComponentType —— 推荐
  2. Component: typeof React.Component
  3. Component: new() => React.Component<any, any>