useState 중복을 custom Hook으로 만들기(ts)

이전 게시글의 훅에서 쓰인 타입을 따로 정리해보려고 한다. (TypeScript 사용 시)

타입 입히기 전

const [email, setEmail] = useState("");
const [nickname, setNickname] = useState("");

const onChangeEmail = useCallback((e) => {
  setEmail(e.target.value);
}, []);

const onChangeNickname = useCallback((e) => {
  setNickname(e.target.value);
}, []);

타입 설정 후

type ReturnTypes<T = any> = [
  T,
  (e: ChangeEvent<HTMLInputElement>) => void,
  Dispatch<SetStateAction<T>>
];

const useInput = <T = any>(initialData: T): ReturnTypes => {
  const [value, setValue] = useState(initialData);

  const handler = useCallback((e: ChangeEvent<HTMLInputElement>) => {
    setValue(e.target.value as unknown as T);
  }, []);
  return [value, handler, setValue];
};

export default useInput;
<T = any>(initialData: T)

useInput는 제너릭 타입 T를 받아들이는데, 이는 초기값의 타입을 나타낸다. 기본값으로 any를 사용한다.

type ReturnTypes<T = any> = [
  T,
  (e: ChangeEvent<HTMLInputElement>) => void,
  Dispatch<SetStateAction<T>>
];

ReturnTypes는 타입을 포함하는 튜플을 정의한다.

T : 초기값 제네릭 타입 T의 타입을 그대로 받는다.

  • any로 설정하면 초기값과 리턴값의 타입이 일치하지 않아도 에러가 뜨지 않는 문제가 안정성 보장이 x

(e: ChangeEvent<HTMLInputElement>) => void : 입력 요소의 값이 변경될 때 호출되는 이벤트 핸들러 함수이다.

Dispatch<SetStateAction<T>> : 상태를 업데이트하는 데 사용

  • SetStateAction<T>는 useState 훅에서 사용되는 상태 업데이트 함수의 인자로 전달되는 값의 타입

제네릭타입(T), any 타입 차이

any: 타입 검사를 피하기 위해 사용하며, 타입 안정성을 보장하지 않아 결국 js와 똑같다.

Generic: 해당 함수나 클래스가 다양한 유형의 데이터를 처리할 수 있도록 만드는 기능이며, 타입 안정성을 보장한다.