Yeah, this is a quirk of how the typings are written:
function useRef<T>(initialValue: T): MutableRefObject<T>;
function useRef<T>(initialValue: T|null): RefObject<T>;
If the initial value includes null, but the specified type param doesn’t, it’ll be treated as an immutable RefObject.
When you do useRef<HTMLInputElement>(null), you’re hitting that case, since T is specified as HTMLInputElement, and null is inferred as HTMLInputElement | null.
You can fix this by doing:
useRef<HTMLInputElement | null>(null)
Then T is HTMLInputElement | null, which matches the type of the first argument, so you hit the first override and get a mutable ref instead.