I am trying to move my React project to Typescript, but without Typescript experience. I have a Component which is defined as follows (trimmed down):
interface InputProps {
handleKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
placeholder: string;
style?: React.CSSProperties;
}
const Input: React.ForwardRefRenderFunction<HTMLInputElement, InputProps> = (
^^^^^
{ handleKeyDown, placeholder, style }: InputProps,
ref: React.MutableRefObject<HTMLInputElement | null>
): JSX.Element => {
return (
<input
ref={ref}
onKeyDown={handleKeyDown}
type="text"
placeholder={placeholder}
style={style}
/>
);
};
export const ForwardedInput = React.forwardRef(Input);
Now I am getting the following TypeScript error on const Input
, and it's a bit too complicated for me to untangle:
TS2322: Type '({ handleKeyDown, placeholder, style }: InputProps, ref: React.MutableRefObject<HTMLInputElement | null>) => JSX.Element'
is not assignable to type 'ForwardRefRenderFunction<HTMLInputElement, InputProps>'.
Types of parameters 'ref' and 'ref' are incompatible.
Type 'MutableRefObject<HTMLInputElement | null> | ((instance: HTMLInputElement | null) => void) | null' is not assignable to type 'MutableRefObject<HTMLInputElement | null>'.
Type 'null' is not assignable to type 'MutableRefObject<HTMLInputElement | null>'.
I'm guessing I need to fix this by changing ref: React.MutableRefObject<HTMLInputElement | null>
into something else, but I don't know how, because I don't know what the error specifically means.
EDIT: The first answer suggested using generic parameters, so I adapted the function as follows:
const Input = ({ handleKeyDown, placeholder, style }: InputProps, ref: any) => {
I had to type props and ref to prevent typescript warnings (I use strict: "true"
), and indeed this removes the warnings in the above code example.
But... using any resulted in:
ESLint: Unexpected any. Specify a different type.(@typescript-eslint/no-explicit-any)
According to this the use of any
should be avoided and unknown
should be used, but although this removes the warning in the function header, it caused a big error in the ref={ref}
on the input component, stating the same incompatibility with ref as my first error. TypeScript is harder than I thought.
You can use generic parameters on React.forwardRef
export const ForwardedInput = React.forwardRef<HTMLInputElement, InputProps>(
(props, ref) => {
const { handleKeyDown, placeholder, style } = props;
return (
<input
ref={ref}
onKeyDown={handleKeyDown}
type="text"
placeholder={placeholder}
style={style}
/>
);
}
);
Playground link
If you need to separate React.forwardRef
call and its function you can use React.ForwardRefRenderFunction
generic type.
const ForwardInputRefFunction: React.ForwardRefRenderFunction<HTMLInputElement, InputProps> = (
props,
ref
) => {
const { handleKeyDown, placeholder, style } = props;
return (
<input
ref={ref}
onKeyDown={handleKeyDown}
type="text"
placeholder={placeholder}
style={style}
/>
);
};
const ForwardedInput = React.forwardRef(ForwardInputRefFunction);
Playground link
You can explore new types by reading definition files in node_modules
. To do it in Code sandbox use Cmd + Left-click
hotkey.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With