Как типизировать forwardRef?

Рейтинг: 1Ответов: 2Опубликовано: 16.02.2023

Имеется такой компонент:

import { forwardRef, Ref } from "react";

export interface ICelebrationScreenProps
{
    title: string;
    [ prop: string ]: any;
}

function CelebrationScreen({ title, ...props }: ICelebrationScreenProps, ref: Ref<HTMLDivElement>)
{
    return (<>{title}</>);
};

export default forwardRef(CelebrationScreen);

Когда я пытаюсь использовать данный компонент в другом файле, VSCode мне не дает подсказок и ошибок о пропсах.

введите сюда описание изображения


Если же я буду использовать компонент без forwardRef, допустим таким способом, то я получу необходимые мне ошибки:

import { forwardRef, Ref } from "react";

export interface ICelebrationScreenProps
{
    title: string;
    [ prop: string ]: any;
}

function CelebrationScreen({ title, ...props }: ICelebrationScreenProps, ref: Ref<HTMLDivElement>)
{
    return (<>{title}</>);
};

export default forwardRef(CelebrationScreen);

function Test()
{
    return <CelebrationScreen />
}

Свойство "title" отсутствует в типе "{}" и является обязательным в типе "ICelebrationScreenProps". ts(2741)

Вы также можете увидеть это поведение на

Edit wonderful-rubin-lvnwpr

Ответы

▲ 3Принят

Для того чтобы наиболее гибко использовать типизацию можно завести определенный интерфейс ForwardRefExoticComponent (подробнее):

import { forwardRef, ReactElement, Ref, WeakValidationMap } from "react";

interface ForwardRefExoticComponent<P> {
  (props: P): ReactElement | null;
  readonly $$typeof: symbol;
  displayName?: string;
  defaultProps?: Partial<P>;
  propTypes?: WeakValidationMap<P>;
}

Сам интерфейс ForwardRefExoticComponent можно не прописывать, а импортировать из реакта.

import { ForwardRefExoticComponent } from "react";

Далее мы сможем использовать его подобным образом, типизируя под конкретные пропсы и получать подстветку ошибки в JSX:

const CelebrationScreenWithRef: ForwardRefExoticComponent<ICelebrationScreenProps> = forwardRef(
  CelebrationScreen
);
▲ -1
// function forwardRef<T, P = {}>(render: ForwardRefRenderFunction<T, P>): 
// ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;

const CelebrationScreen = forwardRef<HTMLDivElement, CelebrationScreenProps>(
({ title }, ref) => {
return (
    <div ref={ref}>{title}</div>
   );
  },
 );