#Forward ref with generics?

5 messages · Page 1 of 1 (latest)

dapper path
#

My goal is to make a component which instances a provider as well as an HTMLDivElement beneath that provider, where it will take all the props of an HTMLDivElement and a ref to forward to that element
for the sake of simplicity, let's say it's as follows:

interface FormFieldProps<TName extends string> extends ComponentPropsWithRef<'div'> {
  name: TName;
}

function FormField<TName extends string>(
  { name, ...props }: FormFieldProps<TName>,
  ref: ForwardedRef<HTMLDivElement>
) {
  // ... this really doesn't matter
}

However, I am having a bit of trouble forwarding the ref, while keeping it generic. I tried the following:

interface FormFieldProps<TName extends string> extends ComponentPropsWithRef<'div'> {
  name: TName;
}

type ForwardFormFieldRef= <TName extends string, T = HTMLDivElement>(render: ForwardRefRenderFunction<T, FormFieldProps<TName>>) => ForwardRefExoticComponent<PropsWithoutRef<FormFieldProps<TName>> & RefAttributes<T>>;

const forwardFormFieldRef = forwardRef as ForwardFormFieldRef;

const FormField = forwardFormFieldRef(FormField);

This doesn't work, though. Anyone got any ideas? This is kinda a PITA ngl

#

it seems like it resolves it to something like this: const FormField: ForwardRefExoticComponent<Omit<FormFieldProps<string>, "ref"> & RefAttributes<HTMLDivElement>>

Typescript Playground link below

coral rockBOT
#
afreyj#0

Preview:```ts
import {
forwardRef,
ForwardRefRenderFunction,
ForwardRefExoticComponent,
ComponentPropsWithRef,
PropsWithoutRef,
RefAttributes,
ForwardedRef,
} from "react"

interface FormFieldProps<TName extends string>
extends ComponentPropsWithRef<"div"> {
name: TName
...```

sharp palm
#

There isn't really a good way to do it; I think the best bad way is just to do it as a non-generic forwardRef and then cast it back to a generic type

#
const FormField = forwardRef<HTMLDivElement, FormFieldProps<string>>(
  ({ name, ...props },
  ref
) => {
  return <></>
}) as <Name extends string>(props: FormFieldProps<Name>) => React.ReactNode