기존 프로젝트를 타입스크립트로 리팩토링 해보기(2) - Index Signatures(인덱스 시그니처), Event Handler

yesung·2023년 12월 14일
1
post-thumbnail

컴포넌트 분리

To-Do List 작업 시 컴포넌트를 총 3개로 나누었다.

  1. 제목과 내용을 작성할 Form
  2. 제목과 내용을 보여줄 List
  3. List에 보여질 Item

useInput 타입 적용

제목과 내용을 작성할 Form

// useInput.ts
type InputState = { [key: string]: string };

export const useInput = (initialState: InputState) => {
  const [values, setValues] = useState<InputState>(initialState);

  const onChangeHandler = useCallback((e: ChangeEvent<HTMLInputElement>) => {
    const { name, value } = e.target;
    setValues(prev => ({ ...prev, [name]: value }));
  }, []);

  const reset = useCallback(() => setValues(initialState), [initialState]);
  return { values, onChangeHandler, reset };
};

// TodoForm.tsx
const { values, onChangeHandler, reset } = useInput({ title: '', content: '' });

우선 2개의 인풋이 필요해서 initialState로 title과 content을 매개변수로 받고 useState의 타입을 지정해주기 위해 타입스크립트 문법인 인덱스 시그니처(Index Signatures) 문법을 사용하여 제네릭으로 선언했다.

아울러 과도한 이벤트 핸들러 호출을 방지하기 위해 useCallback 을 사용하여 onChangeHandler 메모이제이션을 함.

인덱스 시그니처란?
특정 타입의 속성 이름은 알 수 없지만 속성값의 타입을 알고 있을 때 사용하는 문법이다.

만약 위 인덱스 시그니처 문법에서 isVaild: number 이라는 타입을 추가로 지정해주면 에러가 발생된다.

왜냐하면 type 내부에 [key: K]: T 꼴로 타입을 명시해 주어야 한다. 이는 해당 타입의 속성 키는 모두 K 타입이어야 하고 속성값은 모두 T 타입가져야 한다는 의미이기 때문이다.

그러면 이를 방지 하기 위해서는 유니온 타입 으로 & 또는 | 을 string 뒤에 붙여서 표기해주면 된다. [key: string]: string | number

또한, 핸들러의 매개변수 e 에 타입을 부여해주어야 하는데 불필요하게 any 를 줄 순 없으니 타입스크립트에서 이벤트 핸들러 함수에 대해 이벤트 객체의 지정하는 타입이 따로 있었다. 위에서 지정한 ChangeEvent<HTMLInputElement> 이 타입이다.

ChangeEvent란?
ChangeEvent 는 onChange 이벤트와 관련이 있으며, HTMLInputElement<input> 요소에 대한 DOM 객체의 타입을 의미한다.

여기서 ChangeEvent 의 제네릭 타입 <HTMLInputElement> 은 변경 이벤트가 발생하는 대상이 <input> 요소임을 명시해주고 <HTMLInputElement> 는 특정 타입의 <input> 요소를 나타내며, 다른 유형의 HTML 요소에 따라 다른 제네릭 타입을 사용할 수 있다.

profile
Frontend Developer

0개의 댓글