Search code examples
reactjstypescript

Type 'MutableRefObject<HTMLInputElement | undefined>' is not assignable to type 'LegacyRef<HTMLInputElement> | undefined'


Given this very simple component :

const InputElement => React.forwardRef((props:any, ref) => {
    const handleRef = React.useRef<HTMLInputElement|undefined>()
    React.useImperativeHandle(ref, () => ({
        setChecked(checked:boolean) {
            if (handleRef.current) {
                handleRef.current.checked = checked;
            }
        }
    }), []);
    return (
        <input ref={ handleRef } type="checkbox" />  {/* <-- error here */}
    )
})

I have this error :

Type 'MutableRefObject<HTMLInputElement | undefined>' is not assignable to type 'LegacyRef<HTMLInputElement> | undefined'.
  Type 'MutableRefObject<HTMLInputElement | undefined>' is not assignable to type 'RefObject<HTMLInputElement>'.
    Types of property 'current' are incompatible.
      Type 'HTMLInputElement | undefined' is not assignable to type 'HTMLInputElement | null'.
        Type 'undefined' is not assignable to type 'HTMLInputElement | null'.ts(2322)

What does this mean? How to fix this error?


Solution

  • To fix the error, you should pass null as an initial value to the useRef hook. You don't need to add | undefined:

    React.useRef<HTMLInputElement>(null)
    

    The error message says that the ref prop expects a ref of HTMLInputElement | null, but if you pass nothing to the useRef hook, it evaluates to HTMLInputElement | undefined and that's why get the error message:

    Type 'undefined' is not assignable to type 'HTMLInputElement | null'
    

    To better understand what is happening, here is how you could reproduce the same error with a simple function:

    // This function expects a ref similar to how an element like <input> does
    const someFunction = (ref: RefObject<HTMLElement | null>) => {};
    
    // the type of `ref` below will be RefObject<HTMLElement | undefined>
    const ref = useRef<HTMLElement>();
    
    // throws `Type 'undefined' is not assignable to type 'HTMLElement | null'`
    someFunction(ref);
    

    Just how you get the error in the ref prop, you will get the same error in the function call in the last line. If you pass null to the useRef hook, the type of the ref would then become RefObject<HTMLElement | null>, which is compatible with what the function expects, thus no error is thrown.