title: Telling TypeScript that T should be allowed to be instantiated with an arbitrary type
body: <p><strong>EDIT:</strong> <a href="https://codesandbox.io/s/redirect-hoc-example-cbc7m" rel="nofollow noreferrer">Here is a link to a minimal reproducible example.</a> I had to include the external libraries Redux and React Router Dom to reproduce it faithfully.</p>
  <hr />
  <p>I'm building a Next.js app with Redux and TypeScript.</p>
  <p>I have a higher-order higher-order component that hoists statics.</p>
  <pre><code>import hoistNonReactStatics from 'hoist-non-react-statics';
  
  type HOC&lt;Inner, Outer = Inner&gt; = (
    Component: React.ComponentType&lt;Inner&gt;,
  ) =&gt; React.ComponentType&lt;Outer&gt;;
  
  const hoistStatics = &lt;I, O&gt;(higherOrderComponent: HOC&lt;I, O&gt;): HOC&lt;I, O&gt; =&gt; (
    BaseComponent: React.ComponentType&lt;I&gt;,
  ) =&gt; {
    const NewComponent = higherOrderComponent(BaseComponent);
    hoistNonReactStatics(NewComponent, BaseComponent);
    return NewComponent;
  };
  
  export default hoistStatics;
  
  </code></pre>
  <p>Using this, I want to write a <code>redirect</code> HOC that can redirect users based on Redux state. Here is what I have.</p>
  <pre><code>import Router from 'next/router.js';
  import { curry } from 'ramda';
  import { useEffect } from 'react';
  import { connect, ConnectedProps } from 'react-redux';
  import { RootState } from 'redux/root-reducer';
  
  import hoistStatics from './hoist-statics';
  
  function redirect(predicate: (state: RootState) =&gt; boolean, path: string) {
    const isExternal = path.startsWith('http');
  
    const mapStateToProps = (state: RootState) =&gt; ({
      shouldRedirect: predicate(state),
    });
  
    const connector = connect(mapStateToProps);
  
    return hoistStatics(function &lt;T&gt;(
      Component: React.ComponentType&lt;Omit&lt;T, 'shouldRedirect'&gt;&gt;,
    ) {
      function Redirect({
        shouldRedirect,
        ...props
      }: T &amp; ConnectedProps&lt;typeof connector&gt;): JSX.Element {
        useEffect(() =&gt; {
          if (shouldRedirect) {
            if (isExternal &amp;&amp; window) {
              window.location.assign(path);
            } else {
              Router.push(path);
            }
          }
        }, [shouldRedirect]);
  
        return &lt;Component {...props} /&gt;;
      }
  
      return connector(Redirect);
    });
  }
  
  export default curry(redirect);
  </code></pre>
  <p>The problem here is that <code>return connector(Redirect);</code> throws the following TS error.</p>
  <pre><code>Argument of type '({ shouldRedirect, ...props }: T &amp; { shouldRedirect: boolean; } &amp; DispatchProp&lt;AnyAction&gt;) =&gt; Element' is not assignable to parameter of type 'ComponentType&lt;Matching&lt;{ shouldRedirect: boolean; } &amp; DispatchProp&lt;AnyAction&gt;, T &amp; { shouldRedirect: boolean; } &amp; DispatchProp&lt;AnyAction&gt;&gt;&gt;'.
    Type '({ shouldRedirect, ...props }: T &amp; { shouldRedirect: boolean; } &amp; DispatchProp&lt;AnyAction&gt;) =&gt; Element' is not assignable to type 'FunctionComponent&lt;Matching&lt;{ shouldRedirect: boolean; } &amp; DispatchProp&lt;AnyAction&gt;, T &amp; { shouldRedirect: boolean; } &amp; DispatchProp&lt;AnyAction&gt;&gt;&gt;'.
      Types of parameters '__0' and 'props' are incompatible.
        Type 'PropsWithChildren&lt;Matching&lt;{ shouldRedirect: boolean; } &amp; DispatchProp&lt;AnyAction&gt;, T &amp; { shouldRedirect: boolean; } &amp; DispatchProp&lt;AnyAction&gt;&gt;&gt;' is not assignable to type 'T &amp; { shouldRedirect: boolean; } &amp; DispatchProp&lt;AnyAction&gt;'.
          Type 'PropsWithChildren&lt;Matching&lt;{ shouldRedirect: boolean; } &amp; DispatchProp&lt;AnyAction&gt;, T &amp; { shouldRedirect: boolean; } &amp; DispatchProp&lt;AnyAction&gt;&gt;&gt;' is not assignable to type 'T'.
            'T' could be instantiated with an arbitrary type which could be unrelated to 'PropsWithChildren&lt;Matching&lt;{ shouldRedirect: boolean; } &amp; DispatchProp&lt;AnyAction&gt;, T &amp; { shouldRedirect: boolean; } &amp; DispatchProp&lt;AnyAction&gt;&gt;&gt;'.ts(2345)
  </code></pre>
  <p>How can I fix this typing? I thought that telling TypeScript about the &quot;any props&quot; <code>T</code> in <code>hoist-statics</code> and then in <code>Redirect</code>'s props would suffice.</p>