如何定义组件类型?

How do I define component type?

我正在尝试编写一个将 Higher Order Components 作为参数和 returns 与 redux 存储连接的组件的函数。但是这段代码在最后一行有一个类型错误。如何正确定义类型?

import React from 'react'
import { connect } from 'react-redux'
import { Dispatch } from 'redux'
import { AppState } from '~/store'
import { decrement, increment } from '~/store/home'

export type CountableProps = StateType & DispatchType

type StateType = ReturnType<typeof mapStateToProps>
const mapStateToProps = (state: AppState) => ({
  count: state.home.count
})

type DispatchType = ReturnType<typeof mapDispatchToProps>
const mapDispatchToProps = (dispatch: Dispatch) => ({
  increment: () => dispatch(increment()),
  decrement: () => dispatch(decrement())
})

const createCountableComponent =
  <P extends CountableProps>(Component: React.ComponentType<P>) =>
    class extends React.Component<P> {
      componentDidMount() {
        // do something...
      }

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

export const countable = <P extends CountableProps>(Component: React.ComponentType<P>) =>
  connect(
    mapStateToProps,
    mapDispatchToProps
  )(createCountableComponent(Component))

输入错误

TS2345: Argument of type 'typeof ConfigurableComponent' is not assignable to parameter of type 'ComponentType<Matching<CountableProps, P>>'

显式键入连接函数似乎可行:

export const countable = <P extends CountableProps>(Component: React.ComponentType<P>) =>
    connect<StateType, DispatchType, Omit<P, keyof (StateType & DispatchType)>>(
        mapStateToProps,
        mapDispatchToProps
    )(createCountableComponent(Component) as any);

我们可以将 createCountableComponent(Component) 转换为任何类型,因为我们使用正确的类型(state、dispatch 和 ownProps 类型)输入了 connect。这意味着当您使用此组件时,您只会看到不可数的道具(这是所需的解决方案)。

所以:

class Test extends React.Component<{test: string}> {
    render() {
        return <div />;
    }
};

countable(Test)

会报错,而:

class Test extends React.Component<CountableProps & {test: string}> {
    render() {
        return <div />;
    }
};

const Test2 = countable(Test)
<Test2 /> -> intelisense will only give you test now :)

希望对您有所帮助。