title: In React, using TypeScript, how do I pass a ref to a custom component using RefForwardingComponent and forwardRef?
body: <p>I'm trying to pass a ref to a custom component (so that I can set focus to the component). </p>
  
  <p>But I keep getting this error</p>
  
  <pre><code>const RefComp: React.RefForwardingComponent&lt;HTMLInputElement, Props&gt;
  Type '{ value: string; onChange: Dispatch&lt;SetStateAction&lt;string&gt;&gt;; ref: MutableRefObject&lt;HTMLInputElement | undefined&gt;; }'
  is not assignable to type 'IntrinsicAttributes &amp; Props &amp; { children?: ReactNode; }'.
    Property 'ref' does not exist on type 'IntrinsicAttributes &amp; Props &amp; { children?: ReactNode; }'.ts(2322)
  </code></pre>
  
  <p>This is my code</p>
  
  <pre><code>import * as React from 'react';
  import {useRef, useState, RefForwardingComponent, forwardRef} from 'react';
  
  interface Props {
      value: string;
      onChange(event: string): void;
  }
  
  const RefComp: RefForwardingComponent&lt;HTMLInputElement, Props&gt; = forwardRef&lt;
      HTMLInputElement,
      Props
  &gt;(({value, onChange}, ref) =&gt; (
      &lt;input
          value={value}
          onChange={event =&gt; onChange(event.target.value)}
          ref={ref}
      /&gt;
  ));
  
  export default function App() {
      const [val, setVal] = useState('');
      const inputRef = useRef&lt;HTMLInputElement&gt;();
  
      return (
          &lt;div className="App"&gt;
              &lt;RefComp value={val} onChange={setVal} ref={inputRef} /&gt;
              &lt;p&gt;{val}&lt;/p&gt;
          &lt;/div&gt;
      );
  }
  </code></pre>
  
  <p>Here's a codesandbox
  <a href="https://codesandbox.io/s/crimson-cdn-klfp5" rel="noreferrer">https://codesandbox.io/s/crimson-cdn-klfp5</a></p>
  
  <p>The code seems to work fine, if I ignore the error. So not sure why I'm getting it...</p>
  
  <p>Can anyone please explain why I get the error, and how I fix it? :) </p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>As mentioned in the comments you can work around this by adding <code>ref</code> to your props.</p>
  
  <pre><code>import * as React from 'react';
  import {
      useRef,
      useState,
      RefForwardingComponent,
      forwardRef,
      MutableRefObject,
  } from 'react';
  
  interface Props {
      value: string;
      onChange(event: string): void;
      ref?: MutableRefObject&lt;HTMLInputElement | null&gt;;
  }
  
  const RefComp: RefForwardingComponent&lt;HTMLInputElement, Props&gt; = forwardRef&lt;
      HTMLInputElement,
      Props
  &gt;(({value, onChange}, ref) =&gt; (
      &lt;input
          value={value}
          onChange={event =&gt; onChange(event.target.value)}
          ref={ref}
      /&gt;
  ));
  
  export default function App() {
      const [val, setVal] = useState('');
      const inputRef = useRef&lt;HTMLInputElement&gt;(null);
  
      return (
          &lt;div className="App"&gt;
              &lt;RefComp value={val} onChange={setVal} ref={inputRef} /&gt;
              &lt;p&gt;{val}&lt;/p&gt;
          &lt;/div&gt;
      );
  }
  </code></pre>
  
  <p>But this feels wrong. Now we're saying we have <code>ref</code> both as parts of the props, and as a second callback argument to the function passed to <code>forwardRef</code></p>
  
  <p>My issue with this would probably be clearer if I wrote it like this</p>
  
  <pre><code>const RefComp: RefForwardingComponent&lt;HTMLInputElement, Props&gt; = forwardRef&lt;
      HTMLInputElement,
      Props
  &gt;((props: Props, ref) =&gt; (
      &lt;input
          value={props.value}
          onChange={event =&gt; props.onChange(event.target.value)}
          ref={ref /* here, props.ref is also available, but wouldn't work */ }
      /&gt;
  ));
  </code></pre>
  
  <p><strong>EDIT 2:</strong></p>
  
  <p>Here's a related question</p>
  
  <p><a href="https://stackoverflow.com/questions/58991706/typescript-refforwardingcomponent-not-working">Typescript RefForwardingComponent not working</a></p>
  
  <p><strong>EDIT 3:</strong></p>
  
  <p>I found the relevant source code. <a href="https://github.com/DefinitelyTyped/DefinitelyTyped/blob/33f6179e0f25b0ca798ad89a667c0a27ea0c98dd/types/react/index.d.ts#L702" rel="noreferrer">https://github.com/DefinitelyTyped/DefinitelyTyped/blob/33f6179e0f25b0ca798ad89a667c0a27ea0c98dd/types/react/index.d.ts#L702</a></p>
  
  <pre><code>function forwardRef&lt;T, P = {}&gt;(Component: RefForwardingComponent&lt;T, P&gt;): ForwardRefExoticComponent&lt;PropsWithoutRef&lt;P&gt; &amp; RefAttributes&lt;T&gt;&gt;;
  </code></pre>
  
  <p>So the <code>forwardRef</code> function returns a component of type <code>ForwardRefExoticComponent&lt;PropsWithoutRef&lt;P&gt; &amp; RefAttributes&lt;T&gt;&gt;</code>. This is a component that takes props of type <code>PropsWithoutRef&lt;P&gt;</code> intersected with <code>RefAttributes&lt;T&gt;</code>. Both types are also defined in the same file.</p>
  
  <p>From what I understand the first one basically just excludes <code>ref</code> from P (which is <code>Props</code> in my original example). The second one is defined as</p>
  
  <pre><code>interface RefAttributes&lt;T&gt; extends Attributes {
      ref?: Ref&lt;T&gt;;
  }
  </code></pre>
  
  <p>Given this information I really don't understand why I have to add <code>ref</code> to my own <code>Props</code>. It really looks as if <code>forwardRef</code> should do it for me - even going as far as actually removing <code>ref</code> from my own <code>Props</code>...</p>
  
  <p>Can someone please explain what's going on here?</p>