Как определить тип компонента? - PullRequest
0 голосов
/ 26 января 2020

Я пытаюсь написать функцию, которая принимает Higher Order Components в качестве аргумента и возвращает компонент, связанный с избыточным хранилищем. Но этот код имеет ошибку типа в последней строке. Как правильно определить тип?

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>>'

1 Ответ

0 голосов
/ 26 января 2020

Кажется, что явно введена функция соединения:

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). Это означает, что при использовании этого компонента вы увидите только реквизиты, которые не являются счетными (что является желаемым решением).

Итак:

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 :)

Надеюсь, это поможет.

...