Search code examples
reactjstypescriptjsxtsx

Using a forwardRef component with children in TypeScript


Using @types/react 16.8.2 and TypeScript 3.3.1.

I lifted this forward refs example straight from the React documentation and added a couple type parameters:

const FancyButton = React.forwardRef<HTMLButtonElement>((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = React.createRef<HTMLButtonElement>();
<FancyButton ref={ref}>Click me!</FancyButton>;

I get the following error in the last line under FancyButton:

Type '{ children: string; ref: RefObject<HTMLButtonElement>; }' is not assignable to type 'IntrinsicAttributes & RefAttributes<HTMLButtonElement>'. Property 'children' does not exist on type 'IntrinsicAttributes & RefAttributes<HTMLButtonElement>'.ts(2322)

It would seem that the type definition for React.forwardRef's return value is wrong, not merging in the children prop properly. If I make <FancyButton> self-closing, the error goes away. The lack of search results for this error leads me to believe I'm missing something obvious.


Solution

  • You need to pass the button properties:

    import * as React from 'react'
    
    type ButtonProps = React.HTMLProps<HTMLButtonElement>
    
    const FancyButton = React.forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => (
      <button type="button" ref={ref} className="FancyButton">
        {props.children}
      </button>
    ))
    
    // You can now get a ref directly to the DOM button:
    const ref = React.createRef<HTMLButtonElement>()
    
    <FancyButton ref={ref}>Click me!</FancyButton>
    

    ADDED:

    In recent versions of TS and @types/react, you can also use React.ComponentPropsWithoutRef<'button'> instead of React.HTMLProps<HTMLButtonElement>