title: TypeScript connect React-Redux decorator with stateful component
body: <p>I have create an illustrative component <code>Hello</code> where I attempt to use proper types for <code>props</code> and <code>state</code> while using the <code>connect</code> decorator from React-Redux.</p>
  
  <p>You can play along in the <a href="https://github.com/TomasHubelbauer/react-redux-typescript-connect-decorator-demo/commit/b8aa27708fcb12fa4784e78bf5a1957eeb2e722a" rel="nofollow noreferrer">GitHub repository</a> I created to illustrate this.</p>
  
  <p>When <code>connect</code> is <em>not</em> used as a decorator but instead, <code>export default connect(mapStateToProps, mapDispatchToProps)(Hello)</code> is used and the component itself is not exported, this works.</p>
  
  <pre><code>type HelloStateProps = { enthusiasmLevel: number; };
  type HelloDispatchProps = { incrementEnthusiasm: () =&gt; void; decrementEnthusiasm: () =&gt; void; };
  type HelloOwnProps = { name: string; };
  type HelloProps = HelloStateProps &amp; HelloDispatchProps &amp; HelloOwnProps;
  type HelloState = { useHi: boolean; };
  
  // I am getting an error here
  @connect(mapStateToProps, mapDispatchToProps)
  export default class Hello extends React.Component&lt;HelloProps, HelloState&gt; {
    state: HelloState = { useHi: false };
  
    onChangeGreetingButtonClick: React.MouseEventHandler&lt;HTMLButtonElement&gt; = event =&gt;
      this.setState(state =&gt; ({ useHi: !state.useHi }))
  
    render() {
      const { useHi } = this.state;
      const { name, enthusiasmLevel } = this.props;
      return (
        &lt;div className="hello"&gt;
          {useHi ? 'Hi' : 'Hello'} {name} x{enthusiasmLevel}
          &lt;div&gt;
            &lt;button onClick={this.props.decrementEnthusiasm}&gt;-&lt;/button&gt;
            &lt;button onClick={this.props.incrementEnthusiasm}&gt;+&lt;/button&gt;
            &lt;button onClick={this.onChangeGreetingButtonClick}&gt;Change greeting&lt;/button&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      );
    }
  }
  
  export function mapStateToProps({ enthusiasmLevel }: StoreState): HelloStateProps {
    return { enthusiasmLevel };
  }
  
  export function mapDispatchToProps(dispatch: Dispatch&lt;EnthusiasmAction&gt;): HelloDispatchProps {
    return Redux.bindActionCreators({ incrementEnthusiasm, decrementEnthusiasm }, dispatch);
  }
  </code></pre>
  
  <p>The error I am getting when attempting to use <code>connect</code> as a decorator is as follows:</p>
  
  <pre><code>Unable to resolve signature of class decorator when called as an expression.
    Type 'ComponentClass&lt;Pick&lt;HelloProps, "name"&gt;&gt; &amp; { WrappedComponent: ComponentType&lt;HelloProps&gt;; }' is not assignable to type 'typeof Hello'.
      Type 'Component&lt;Pick&lt;HelloProps, "name"&gt;, ComponentState&gt;' is not assignable to type 'Hello'.
        Types of property 'state' are incompatible.
          Type 'Readonly&lt;ComponentState&gt;' is not assignable to type 'HelloState'.
            Property 'useHi' is missing in type 'Readonly&lt;ComponentState&gt;'.
  </code></pre>
  
  <p>When I strip the component of state fully, like this:</p>
  
  <pre><code>@connect(mapStateToProps, mapDispatchToProps)
  export default class Hello extends React.Component&lt;HelloProps&gt; {
    render() {
      const { name, enthusiasmLevel } = this.props;
      return (
        &lt;div className="hello"&gt;
          Hi {name} x{enthusiasmLevel}
          &lt;div&gt;
            &lt;button onClick={this.props.decrementEnthusiasm}&gt;-&lt;/button&gt;
            &lt;button onClick={this.props.incrementEnthusiasm}&gt;+&lt;/button&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      );
    }
  }
  </code></pre>
  
  <p>…I get this error instead:</p>
  
  <pre><code>Unable to resolve signature of class decorator when called as an expression.
    Type 'ComponentClass&lt;Pick&lt;HelloProps, "name"&gt;&gt; &amp; { WrappedComponent: ComponentType&lt;HelloProps&gt;; }' is not assignable to type 'typeof Hello'.
      Type 'Component&lt;Pick&lt;HelloProps, "name"&gt;, ComponentState&gt;' is not assignable to type 'Hello'.
        Types of property 'render' are incompatible.
          Type '() =&gt; string | number | false | Element | Element[] | ReactPortal | null' is not assignable to type '() =&gt; Element'.
            Type 'string | number | false | Element | Element[] | ReactPortal | null' is not assignable to type 'Element'.
              Type 'null' is not assignable to type 'Element'.
  </code></pre>
  
  <p>Where is the problem? I don't understand the error messages.</p>
  
  <p>In the stateful one, <code>state</code> should make 0 difference to <code>connect</code>, right? So why is it even reported? And <code>useHi</code> is most certainly not missing in <code>ReadOnly&lt;HelloState&gt;</code>, but where is <code>ComponentState</code> coming from?</p>
  
  <p>In the stateless one, <code>render</code>, when hovered over, shows <code>JSX.Element</code> return type. So what is up with that <code>null</code>?</p>