anon_dcs3spp
anon_dcs3spp

Reputation: 3022

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

I am a new react/redux user struggling to get a higher order component connected to redux store through connect function. My code is as follows...

Redux state and dispatch props

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

export const dispatchProps = {
  clearError: clearErrorAction,
};

Higher Order Component

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;
};

When I try to hook up the connect function to the higher order component I receive the following error informing that types of parameters 'props' and 'props' are incompatible. I think it is related to dispatch properties?? Has anyone experienced anything similar?

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

Upvotes: 2

Views: 1254

Answers (1)

anon_dcs3spp
anon_dcs3spp

Reputation: 3022

The issue was incorrect typing of the connect function in the HoC.

After some refactoring and a secondary question here managed to solve the issue with some help from the author of react-redux-typescript-guide](https://github.com/piotrwitek/react-redux-typescript-guide) managed to get it working.

The HoC was refactored to follow the pattern suggested in the react-redux-typescript-guide.

I created a codesandbox in the event that others encounter a similar issue.

Upvotes: 2

Related Questions