Search code examples
reactjstypescripttypescript-genericstypeguardsreact-forwardref

Typescript React forwardRef with Union/Generic Element


I'm trying to implement element that can be div or button element


type customElement = HTMLDivElement | HTMLDivElement   .....

const Element = React.forwardRef<customElement, somePropInterface>((props,ref)=>{
  if(someCase){
   return <div ref={ref}
  }else if(someCase2){
   return <button ref={ref}
  }else{
   return <a ref={ref}
  }
})

or Generic case

const Element = React.forwardRef((props,ref)=>{
  return <T ref={ref}/> // element with T...
})

Problem is that it is not easy to type guard React.ref each case for typescript(div, a, button...)

I tried to use custom typeguard but not sure what to check for each element

function isDivRef(
  ref: React.Ref<HTMLDivElement>,
  element: "div" | "button"
): ref is React.Ref<HTMLDivElement> {
  return ?????
}

Solution

  • I was facing the same issue in a project I'm working on. After trying a few different combinations using union types, I found out -- by trial and error -- that to use more than one type with React.forwardRef, it's required to use an intersection instead of a union. This way:

    const Element = React.forwardRef<HTMLAnchorElement & HTMLButtonElement, Props>(
      (props, ref) => {
        if (...) {
          return <a ref={ref} ... />
        }
        return <button ref={ref} ... />
      }
    );