Как типизировать 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);
Когда я пытаюсь использовать данный компонент в другом файле, 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)
Вы также можете увидеть это поведение на
Ответы (3 шт):
// 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>
);
},
);
Я думаю, что это происходит потому, что при использовании forwardRef компонент оборачивается в HOC (Higher-Order Component), который может изменять типы пропсов. В данном случае, тип пропсов компонента CelebrationScreen после обертки forwardRef становится неявным и VSCode не может определить его автоматически.
Чтобы решить эту проблему, можно явно указать тип пропсов при использовании компонента:
import { forwardRef, Ref } from "react";
import { ICelebrationScreenProps } from "./CelebrationScreen";
function Test()
{
const ref = useRef<HTMLDivElement>(null);
const props: ICelebrationScreenProps = {
title: "My Title",
myCustomProp: "Custom Value"
};
return <CelebrationScreen {...props} ref={ref} />;
}
В этом случае, VSCode будет иметь доступ к типу пропсов и сможет предоставлять подсказки и ошибки при работе с компонентом.
Для того чтобы наиболее гибко использовать типизацию можно завести определенный интерфейс 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
);

