DEV Community

Discussion on: Ref forwarding with React function components and Typescript

Collapse
 
roblevintennis profile image
Rob Levin • Edited

You should hear from the ether that this helped me :) I looked at many examples and was fiddling quite a while until this worked for me. I used the 3rd pattern.

Fwiw, I found the return type of ReactElement to work as the index.d.ts I had didn't appear to export JSX (anymore because I've definitely used that in the past).

I find it interesting the number of hoops I have to jump through just to implement a keyboard navigation handler in react + TS but I guess that's the world of modern FE development ¯_(ツ)_/¯

Collapse
 
jexperton profile image
Jonathan Experton • Edited

the @types/react module should declare the global JSX namespace here:

declare global {
    namespace JSX {
        interface Element extends React.ReactElement<any, any> { }
Enter fullscreen mode Exit fullscreen mode

As you can see JSX.Element is an alias of React.ReactElement<any, any> so that's probably why it works for you.

I sometimes find myself working harder on typing rather than on the code itself, but if you see typing as the only standardized, accurate and up-to-date documentation you can enforce (with a linter and git hooks), it worth the effort.

Then you still have to deal with the most difficult problem in programming: picking good names.

Collapse
 
roblevintennis profile image
Rob Levin • Edited

Yeah, I think I was doing something wrong to not be able to use JSX.Element but I forget the exact error.

Regarding it being worth the effort I'm still on the fence myself. I think Typescript is a great place to apply the Pareto Principle. I barely use generics and I'm going to let that happen naturally (or not), but I'm not willing to invest as much time as it would take to learn a new language just to please Typescript. But yeah, I like the type safety overall. Applying what you described for React.forwardRef today on my project:

export const TabButton = React.forwardRef<HTMLButtonElement, TabButtonProps>(
  (
    {
...bunch of props
    }: TabButtonProps,
    tabRef: React.ForwardedRef<HTMLButtonElement>,
  ): ReactElement => {...}
Enter fullscreen mode Exit fullscreen mode

is about as terse as I'm willing to go for now. Maybe I'll surprise myself and get more fancy later down the road :-)