TypeScript: 타입 지정

5460 단어 typescriptReactReact

타입스크립트로 프로젝트를 진행하다보면 어떤 타입을 지정해줘야 할 지 몰라서 any를 쓰는 경우가 많아진다. 하지만, any를 사용하게 될 경우 타입의 검사를 실행하지 않게 된다. 타입스크립트를 사용하는 이유가 런타임 이전에 타입을 검사하여 오류를 먼저 잡아내기 위한 것인데, any의 사용은 이러한 타입스크립트의 장점을 모두 묻어버린다. 이 글에서는 처음 타입스크립트에 입문했을 때 알기 어려웠던 몇 가지 타입들에 대해 기록해두려 한다.

React.ChangeEvent<HTMLInputElement>

컴포넌트에서 상태가 변경되었을 때, 버튼을 클릭했을 때 등 이벤트를 발생시키는 경우가 많다. 이럴 때 사용하는 메소드가 onClick, onInput, onChange 등이 있다. 이러한 이벤트를 발생시키는 경우 인자로 이벤트 객체를 사용하는 경우가 많은데, 이 이벤트의 타입을 어떻게 정의해줘야 할 지 몰라서 any를 쓰는 경우가 많다. 이벤트 객체는 아래와 같이 React.ChangeEvent<HTMLInputElement> 등의 타입을 지정해주면 any의 사용을 피할 수 있다.

import React, { useState } from 'react';

const Component = () => {
  const [state, setState] = useState('');
  
  const changeState = (e: React.changeEvent<HTMLInputElement>) => {
    setState(e.target.value);
  }
  return (
    <input type="text" onInput={changeState}></input>
  );
}

이벤트 객체의 타입에는 changeEvent 뿐만 아니라 mouseEvent, dragEvent 등도 있다.

map 객체는 interface 사용

map 객체의 경우에는 interface를 사용하면 any의 사용을 피할 수 있다.

import imageOne from './imageOne.svg';
import imageTwo from './imageTwo.svg';

interface mapInterface {
  [prop: string]: string;
}

const images: mapInterface = {
  1: imageOne,
  2: imageTwo,
}

const RenderImages = () => {
  // 다른 이미지를 렌더링하기 위해서는 imageNumber 상태를 변경해줘야 한다.
  const [imageNumber, setImageNumber] = useState(1);
  
  return (
    <img src={images[String(imageNumber)]}></img>
  );
}

setState 상태 관리 메소드는 () => void를 사용

함수의 타입은 반환하는 값이 있을 경우 () => {} 형식으로 표현하고, 반환하는 값이 없을 경우 () => void 형식으로 표현한다. setState 메소드의 경우에는 상태만 변경하고 반환하는 값이 없기 때문에, 이 메소드를 다른 컴포넌트의 인자로 넘겨주는 경우에는 void를 사용해주어야 한다. 이 때, setState 메소드는 항상 state 상태를 파라미터로 받으므로, 파라미터의 타입도 정의해주어야 한다.

// 상위 컴포넌트
const Upper = () => {
  const [word, setWord] = useState('');
  
  return (
    <Lower word={word} setWord={setWord} />
  );
}

// 하위 컴포넌트
const Lower = ({ word: string; setWord: (word: string) => void }) => {
  setWord(word);
  return (
    <div></div>
  );
}

fetch 응답은 Response 타입

fetch 비동기 요청을 보낸 후 서버에서 받은 응답은 Response 타입을 사용하면 any의 사용을 피할 수 있다.

interface resInterface {
  [prop: string]: string;
}

const App = () => {
  useEffect(() => {
    const getData = async () => {
      const res: Response = await fetch('/api/data');
      const data: Array<resInterface> = await res.json();
    }
    getData();
  }, []);
  
  return (
    <div></div>
  );
}

참고 자료

TypeScript를 사용하는 이유
복합형 객체, JSON, MAP 사용 방법

좋은 웹페이지 즐겨찾기