如何解决 Redux React Typescript Higher Order Component (Hoc) compile error "props and props" are incompatible

How to solve Redux React Typescript Higher Order Component (Hoc) compile error "props and props" are incompatible

我是一个新 react/redux 用户,正在努力通过 connect 函数将高阶组件连接到 redux store。我的代码如下...

Redux 状态和调度道具

export const mapStateToProps = (
  state: RootState,
  ownProps: ApiErrorComponentInjectedProps,
): StateProps => ({
  error: filterErrors(state.errors as StateProps, ownProps),
});

export const dispatchProps = {
  clearError: clearErrorAction,
};

高阶分量

import * as redux from './reduxConnect';

type ApiErrorDispatchProps = typeof redux.dispatchProps;
type ApiErrorStateProps = ReturnType<typeof redux.mapStateToProps>;

export const withReduxErrorListener = <
  BaseProps extends ApiErrorComponentInjectedProps
>(
  ChildComponent: ComponentType<BaseProps>,
) => {
  /**
   * @typename HocProps  Base properties passed into component, ReturnType<mapStateToProps>, typeof dispatchProps, RouteComponentProps
   */
  type HocProps = BaseProps &
    ApiErrorStateProps &
    ApiErrorDispatchProps &
    RouteComponentProps;

  /**
   * Higher Order Component (HoC)
   */
  class ApiErrorListener extends React.Component<HocProps, {}> {

    /**
     * Pass properties to base constructor
     * @param props  Initialisation properties
     */
    constructor(props: HocProps) {
      super(props);
    }
   ...
  }

  const ConnectedHoc = connect<
    ApiErrorStateProps,
    ApiErrorDispatchProps,
    HocProps,
    RootState
  >(
    mapStateToProps,
    dispatchProps,
  )(ApiErrorListener); // this is causing a compilation error

  return ConnectedHoc;
};

当我尝试将连接函数连接到高阶组件时,我收到以下错误消息,通知我参数类型 'props' 和 'props' 不兼容。我认为这与调度属性有关??有没有人经历过类似的事情?

  TS2345: Argument of type 'typeof ApiErrorListener' is not assignable to parameter of type 'ComponentType<Matching<StateProps & { clearError: (raisingAction: string, sourceComponent: string, history?: History<any> | undefined, navigateTo?: string | undefined) => PayloadAction<constants.CLEAR_API_ERROR, ClearError>; }, HocProps>>'.
  Type 'typeof ApiErrorListener' is not assignable to type 'ComponentClass<Matching<StateProps & { clearError: (raisingAction: string, sourceComponent: string, history?: History<any> | undefined, navigateTo?: string | undefined) => PayloadAction<constants.CLEAR_API_ERROR, ClearError>; }, HocProps>, any>'.
    Types of parameters 'props' and 'props' are incompatible.
      Type 'Matching<StateProps & { clearError: (raisingAction: string, sourceComponent: string, history?: History<any> | undefined, navigateTo?: string | undefined) => PayloadAction<constants.CLEAR_API_ERROR, ClearError>; }, HocProps>' is not assignable to type 'HocProps'.
        Type 'Matching<StateProps & { clearError: (raisingAction: string, sourceComponent: string, history?: History<any> | undefined, navigateTo?: string | undefined) => PayloadAction<constants.CLEAR_API_ERROR, ClearError>; }, HocProps>' is not assignable to type 'BaseProps'.
          'Matching<StateProps & { clearError: (raisingAction: string, sourceComponent: string, history?: History<any> | undefined, navigateTo?: string | undefined) => PayloadAction<constants.CLEAR_API_ERROR, ClearError>; }, HocProps>' is assignable to the constraint of type 'BaseProps', but 'BaseProps' could be instantiated with a different subtype of constraint 'ApiErrorComponentInjectedProps'.
            Type 'P extends "error" | "clearError" ? (StateProps & { clearError: (raisingAction: string, sourceComponent: string, history?: History<any> | undefined, navigateTo?: string | undefined) => PayloadAction<...>; })[P] extends HocProps[P] ? HocProps[P] : (StateProps & { ...; })[P] : HocProps[P]' is not assignable to type 'BaseProps[P]'.
              Type '((StateProps & { clearError: (raisingAction: string, sourceComponent: string, history?: History<any> | undefined, navigateTo?: string | undefined) => PayloadAction<constants.CLEAR_API_ERROR, ClearError>; })[P] extends HocProps[P] ? HocProps[P] : (StateProps & { ...; })[P]) | HocProps[P]' is not assignable to type 'BaseProps[P]'.
                Type '(StateProps & { clearError: (raisingAction: string, sourceComponent: string, history?: History<any> | undefined, navigateTo?: string | undefined) => PayloadAction<constants.CLEAR_API_ERROR, ClearError>; })[P] extends HocProps[P] ? HocProps[P] : (StateProps & { ...; })[P]' is not assignable to type 'BaseProps[P]'.
                  Type '(StateProps & { clearError: (raisingAction: string, sourceComponent: string, history?: History<any> | undefined, navigateTo?: string | undefined) => PayloadAction<constants.CLEAR_API_ERROR, ClearError>; })[P] | HocProps[P]' is not assignable to type 'BaseProps[P]'.
                    Type '(StateProps & { clearError: (raisingAction: string, sourceComponent: string, history?: History<any> | undefined, navigateTo?: string | undefined) => PayloadAction<constants.CLEAR_API_ERROR, ClearError>; })[P]' is not assignable to type 'BaseProps[P]'.
                      Type 'StateProps & { clearError: (raisingAction: string, sourceComponent: string, history?: History<any> | undefined, navigateTo?: string | undefined) => PayloadAction<constants.CLEAR_API_ERROR, ClearError>; }' is not assignable to type 'BaseProps'.
                        Type 'HocProps["history"] | HocProps["location"] | HocProps["match"] | HocProps["staticContext"] | (IApiFailure[] extends HocProps["error"] ? HocProps["error"] : IApiFailure[]) | ((raisingAction: string, sourceComponent: string, history?: History<...> | undefined, navigateTo?: string | undefined) => PayloadAction<...> ext...' is not assignable to type 'BaseProps[P]'.
                          Type 'BaseProps["history"] & History<any>' is not assignable to type 'BaseProps[P]'.

问题是 HoC 中连接函数的键入不正确。

经过一些重构和一个次要问题 managed to solve the issue with some help from the author of react-redux-typescript-guide](https://github.com/piotrwitek/react-redux-typescript-guide) 设法让它工作。

HoC 已重构,以遵循 react-redux-typescript-guide 中建议的pattern

我创建了一个 codesandbox 以防其他人遇到类似问题。