개발자 첫걸음/에러일지
Type 'MutableRefObject<string>' is not assignable to type 'LegacyRef<HTMLInputElement> | undefined'. Type 'MutableRefObject<string>' is not assignable to type 'RefObject<HTMLInputElement>'. Types of property 'current' are incompatible. Type 'st..
프로아마추어
2022. 8. 10. 03:01
타입스크립트를 적용한 프로젝트에서 useRef를 사용할 때 발생한 에러이다.
에러가 발생한 코드
// useRef에 generic형태로 type을 지정해주자.
const enteredInputValue = useRef();
const updateInputValue = () => {
enteredInputValue.current.value += 1;
}
<input ref={enteredInputValue} type="text" />
<button onClick={updateInputValue}>클릭</button>
아래 3가지 경우에 대응하는 조건을 찾아 위 코드의 generic값을 바꿔주자
1. useRef의 초기값과 generic 타입이 일치할 때
const enteredInputValue = useRef<number>(0);
// MutableRefObject를 반환하기 때문에 ref를 사용할 수 없다.
// <input ref={enteredInputValue} type="text" />
2. useRef의 초기값이 null 일 때
const enteredInputValue = useRef<HTMLInputElement>(null);
const updateInputValue = () => {
enteredInputValue.current.value += parseInt(1);
}
3. useRef의 초기값이 undefined일 때
const enteredInputValue = useRef<HTMLInputElement>();
아래 참고 사이트를 확인해보면 useRef는 초기값에 따라 3가지의 반환 형태를 가진다.
(함수의 인자 값의 타입만 다르기 때문에 오버로딩되고 있음.)
// useRef와 초기값의 타입이 일치하면 MutableRefObject 객체를 반환
function useRef<T>(initialValue: T): MutableRefObject<T>;
// 초기값의 타입이 null이라면 RefObject 객체를 반환
function useRef<T>(initialValue: T|null): RefObject<T>;
// 초기값의 타입이 undefined이라면 MutableRefObject 객체를 반환
function useRef<T = undefined>(): MutableRefObject<T | undefined>;
그러면 MutableRefObject와 RefObject 객체는 무엇을 의미하는 것일까?
interface MutableRefObject<T> {
current: T;
}
interface RefObject<T> {
readonly current: T | null;
}
useRef는 위와 같이 MutableRefObject 객체의 경우 current property에 접근하여 해당 값을 바꿔주고 있다.
하지만 RefObject는 단순히 current property의 값을 읽을 수만 있다.
결론
- useRef의 초기값과 제네릭의 타입이 일치하면 해당 타입을 명시해준다. -> 로컬 변수 용도로 사용할 때
- useRef의 초기값을 null로 정해준다면 ref를 명시해줄 HTML tag 요소를 타입으로 넣어주자. -> ex) HTMLInputElement -> DOM요소를 조작할 때
참고 사이트
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L1021-L1065
https://driip.me/7126d5d5-1937-44a8-98ed-f9065a7c35b5