title: Typescript: React.forwardRef with generic props from @material-ui
body: <p>I'm trying to add custom logic on top of @material-ui Button component.To do so, I'm creating a component that is wrapping the original Button and it runs properly.</p>
  <p>My issue is to have this properly typed, especially to get the props from the original component. I had it working by following <a href="https://material-ui.com/guides/typescript/#usage-of-component-prop" rel="noreferrer">https://material-ui.com/guides/typescript/#usage-of-component-prop</a> until I added <code>React.forwardRef()</code>.</p>
  <p>Working version without <code>forwardRef</code>:</p>
  <pre><code>import { Button, ButtonProps } from '@material-ui/core'
  import React from 'react'
  
  type ExtraProps = {
    target?: string
    rel?: string
    href?: string
    color?: 'default' | 'primary' | 'secondary'
  }
  
  // see https://material-ui.com/guides/typescript/#usage-of-component-prop
  type Props&lt;C extends React.ElementType&gt; = ButtonProps&lt;C, { component?: C }&gt; &amp; ExtraProps
  
  const CustomButton = &lt;C extends React.ElementType&gt;({
    children,
    target,
    rel,
    href,
    ...rest
  }: Props&lt;C&gt;) =&gt; {
    const relValue = target === '_blank' ? 'noopener noreferrer' : rel
  
    const linkValues = href ? { href, target, rel: relValue } : undefined
  
    return (
      &lt;Button {...linkValues} {...rest}&gt;
        {children}
      &lt;/Button&gt;
    )
  }
  </code></pre>
  <p>Non-working version with <code>React.forwardRef</code>:</p>
  <pre><code>import { Button, ButtonProps } from '@material-ui/core'
  import React from 'react'
  
  type ExtraProps = {
    target?: string
    rel?: string
    href?: string
    color?: 'default' | 'primary' | 'secondary'
  }
  
  // see https://material-ui.com/guides/typescript/#usage-of-component-prop
  export type Props&lt;C extends React.ElementType&gt; = ButtonProps&lt;C, { component?: C }&gt; &amp; ExtraProps
  
  const CustomButton = React.forwardRef&lt;HTMLButtonElement, Props&lt;React.ElementType&gt;&gt;(
    ({ children, target, rel, href, ...rest }, ref) =&gt; {
      const relValue = target === '_blank' ? 'noopener noreferrer' : rel
  
      const linkValues = href ? { href, target, rel: relValue } : undefined
  
      return (
        &lt;Button {...linkValues} {...rest} ref={ref}&gt;
          {children}
        &lt;/Button&gt;
      )
    }
  )
  </code></pre>
  <p>When I say &quot;non-working&quot;, it's because the type of <code>CustomButton</code> is:</p>
  <pre><code>React.ForwardRefExoticComponent&lt;Pick&lt;Props&lt;React.ElementType&lt;any&gt;&gt;, string | number | symbol&gt; &amp; React.RefAttributes&lt;HTMLButtonElement&gt;&gt;
  </code></pre>
  <p>instead of</p>
  <pre><code>&lt;C extends React.ElementType&lt;any&gt;&gt;({ children, target, rel, href, ...rest }: Props&lt;C&gt;) =&gt; JSX.Element
  </code></pre>
  <p>It means I can pass any props to my <code>CustomButton</code> and TS will not enforced the contract at all.</p>
  <p>How should I fix the version with <code>React.forwardRef()</code> in order to have correct typing?</p>
  <p>Codesandbox demo: <a href="https://codesandbox.io/s/boring-hertz-0hutt?file=/src/App.tsx" rel="noreferrer">https://codesandbox.io/s/boring-hertz-0hutt?file=/src/App.tsx</a></p>