0
votes

I'm trying to create type-safe HOC going with TypeScript and react-redux.

hoc/with-is-visible-range.tsx

import React from "react";
import { Subtract } from "utility-types";
import { connect } from "react-redux";
import { rangeVisibilitySelector } from "./date-range.selectors";

interface IInjectedProps {
  visible: boolean;
}

interface IMappedProps {
  isVisible: boolean;
}

const withIsVisibleRange = <T extends IInjectedProps>(
  Component: React.ComponentType<T>
) => {
  const WrappedComponent: React.SFC<
    Subtract<T, IInjectedProps> & IMappedProps
  > = ({ isVisible, ...rest }: IMappedProps) => {
    return <Component {...rest} visible={isVisible} />;
  };

  const mapStateToProps = (state: ApplicationState) => ({
    isVisible: rangeVisibilitySelector(state)
  });

  return connect(
    mapStateToProps,
    null
  )(WrappedComponent);
};

export default withIsVisibleRange;

But I always get the same error:

Error message:

Error:(30, 5) TS2345: Argument of type 'StatelessComponent> & IMappedProps>' is not assignable to parameter of type 'ComponentType> & IMappedProps>>'. Type 'StatelessComponent> & IMappedProps>' is not assignable to type 'StatelessComponent> & IMappedProps>>'. Type 'Pick> & IMappedProps' is not assignable to type 'Matching<{ isVisible: boolean; } & null, Pick> & IMappedProps>'. Type '(Pick> & IMappedProps)[P]' is not assignable to type 'P extends "isVisible" ? ({ isVisible: boolean; } & null)[P] extends (Pick> & IMappedProps)[P] ? (Pick> & IMappedProps)[P] : ({ ...; } & null)[P] : (Pick<...> & IMappedProps)[P]'.

1

1 Answers

0
votes

While the type manipulations (Matching, etc.) used in the declaration of connect in @types/react-redux work for any given props type, the TypeScript compiler is unable to reason symbolically about what happens when they are applied to a props type involving a type parameter T. Unfortunately, you'll have to use a type assertion, i.e., WrappedComponent as any.