[TS] 타입스크립트 시작하기

김zunyange·2023년 10월 15일
0

TypeScript

목록 보기
3/3
post-thumbnail

개발을 시작하면서 초반 자바스크립트 잠깐 하고, 몇 달간 리액트만 쭉 사용하다가 타입스크립트를 사용해보고자 타입스크립트 기반의 사이드 프로젝트를 하게 되었다. 프로젝트 전에 어느정도 기초 공부를 했어야 했는데, 순식간에 시작이 되어버려 무지한 상태로 코드를 치려다보니 그냥 복붙만 계속 하고 있었고, 대충 이런느낌인가? 에러만 없음 됐지 뭐~ GPT야 도와줘! 하다가 벌써 레이아웃 완성이 되어버렸다. 그래서 기능구현을 하기 전에 얼렁 타입스크립트를 어느정도는 잡고 가야한다. 🚀

타입스크립트란?

타입스크립트는 언어의 기본 사용법과 문법은 자바스크립트와 동일하지만, 타입을 추가적으로 선언한다는 차이가 있다.

타입스크립트를 사용하면 동적인 자바스크립트의 변수를 정적으로 바꿔주기 때문에 타입스크립트 컴파일 과정에서 에러를 미리 잡아줄 수 있고, 에러에 대한 메세지가 구체적으로 자세하게 나오기 때문에 최근 프론트엔드 개발자들을 중심으로 선호되고 있는 추세라고 한다.

💡 현재 프로젝트에서 레이아웃 구현까지 완료됐다고 했는데, 아직까지는 리액트와 크게 다를게 없이 단지 state, props, function, event 등에 타입을 선언해준다는 점이 기존의 React와의 가장 큰 차이점임을 알 수 있었다.

State

const [data, setData] = useState<boolean>(false);

아래의 코드 예제와 같이 초기값을 설정해두는 경우에는 따로 타입을 선언하지 않아도 자동으로 타입을 추정해 준다.

type Information = { name: string; description: string };
const [info, setInformation] = useState<Information | null>(null);

참고로 배열인 경우에는 해당 배열이 어떤 타입으로 이루어진 배열인지 추론할 수 있도록 Generics을 명시하는 것이 좋다. 그리고 만약 다음과 같이 객체의 타입을 선언하는 경우에 타입이 반복 사용되는 경우라면 interfacetype을 이용하여 따로 생성해주는 것이 좋다.

// interface
interface loc {
  title: string,
  y: number,
  x: number
}
// type
type loc = {
  title: string,
  y: number,
  x: number
}

const Store:React.FC =()=>{
  const [curLoc, setCurLoc] = React.useState<loc>();
  return(<></>)
}

Props

스타일 컴포넌트를 사용하는 이유는 컴포넌트 관리와 스타일링을 동시에 사용할 수 있기 때문이다. 특히 스타일 컴포넌트에서 props를 스타일링할 때 편하게 사용할 수 있기에 더욱 많이 사용되는데 props를 받을때도 타입을 지정해야 했다. 이 부분에서 어려웠던 점은 하나의 props를 받을 때, 다수의 props를 받을 때와 방식이 다르다는 점이다.

1개의 props

아래의 코드와 같이 받는 props의 타입 지정

const Container = styled.div< { age : number } >`
  color: ${(props) => (props.age > 20 ? 'red' : 'gray')};
`;

다수의 props

다수의 props를 받을 시 Interface를 꼭 사용 !

// 상속컴포넌트의 타입 상속받기
interface Container {
  isActive: boolean;
  age: number;
  프롭스명: 타입지정;
}

// 상속받은 컴포넌트에 타입 추가하기
const Container = styled(상속받을 컴포넌트명)<Container>`
  color: ${(props) => (props.age > 20 ? 'red' : 'gray')};
  background-color: ${(props) => (props.isActive ? 'red' : 'gray')};
`;

부모 컴포넌트에서 자식 컴포넌트로 전달하는 props

일단 기본적으로 부모 컴포넌트에서 자식 컴포넌트로 props를 전달할때, 자식 컴포넌트에서 props의 타입을 지정해줘야 한다. 처음에 아래와 코드와 같이 작성했었는데, 이렇게 작성하면 안된다. props는 자식컴포넌트에서 타입을 지정해줘야 하기 때문이다.

//잘못된 작성법
export default function MainComments(props: { comment: string }) { 
  return (
    <li>
      Seokho__lee {commentItem}
      <FiHeart></FiHeart>
    </li>
  );
}

1개의 props

받아오는 props를 자식 컴포넌트에서 직접 타입을 지정

export default function MainComments({ commentItem }: { comment: string }) { 
  return (
    <li>
      Seokho__lee {commentItem}
      <FiHeart></FiHeart>
    </li>
  );
}

다수의 props

1개의 props는 직접 타입을 지정해주면 되지만, 여러개의 props를 받는다면 다른 형태로 작성해야 한다. 물론 1개의 props를 받을때처럼 작성해도되긴 하지만 가독성 측면에서 아주 좋지 않다.
결론적으로 다수의 props를 받을때는 Interface를 사용하는 것! (type도 사용 가능)

//type을 사용했을 때의 예시
export type UserType = {
  name: string
  age: number
  position: string
}

export default function User ({name, age, position}: UserType) {
  
  return (
    <div>
      <p>이름: {name}</p>
      <p>나이: {age}</p>
      <p>포지션: {position}</p>
    </div>
  )
}

다수의 props + 함수

사실 1개 혹은 다수의 props를 받는 것은 매우 간단한 편이고 형태만 알면 쉽게 작성할 수 있다. 하지만 함수를 props로 받을 때 약간 헷갈릴 수 있다.

일단 자식컴포넌트에서 props의 타입을 지정할때 Interface를 자주 사용하게 되는데, Interface의 이름 앞에 'I' 를 통상적으로 사용한다. I의 뜻은 Interface라는 뜻이다.

또한, 함수를 받을때의 형태가 어색한데, '파라미터'의 유무에 따라 따라서 형태가 달라진다.

import { CommentsType } from '../../../Type/Interface';

interface IProps {
  commentList: CommentsType;
  removeComments: () => void; // 파라미터와 함수의 return이 없을 경우
  removeComments: (id: number) => void; // 파라미터가 있고 함수의 return이 없을 경우
}

export default function MainComments({ commentList, removeComments }: IProps) {
  return ()
};

Function

React 함수에서도 타입스크립트 사용법은 비슷하다. 즉 들어오는 인자의 타입을 선언해주고, 추가적으로 인자 뒤에 함수의 반환 타입까지 선언해줄 수 있다.

const FunctionName = (id: string) :void => {
  /*생략*/
}

Event

React에서 타입스크립트를 적용하면서 가장 까다로운 부분이 바로 이벤트다. React의 요소에 어떤 타입을 선언할지 헷갈릴 수 있기 때문이다.
나는 Event를 작성할때마다 리서칭을 통해서 어떤 타입을 지정해줘야할지 알아보면서 해결했다. 물론 마우스 오버하면 타입을 알려주지만, 나와 같이처음 타입스크립트를 공부하는 사람들은 열심히 리서칭해서 여러 참고 문서와 글을 보면서 지정하는게 좋다고 생각한다.

onChange

React.ChangeEvent 로 이벤트가 사용된다.

const updateComment = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      setComment(e.target.value);
    },
    [setComment]
  );

onClick

React.MouseEventHandler 로 이벤트가 사용된다.

const updateComment = useCallback(
    (e: React.MouseEvent<HTMLButtonElement>) => {
      setComment(e.target.value);
    },
    [setComment]
  );

onKeyPress

React.KeyboardEvent 로 이벤트가 사용된다.

const keyEnter = useCallback(
    (e: React.KeyboardEvent<HTMLInputElement>) => {
      if (e.key === 'Enter') {
        addFeedComment();
      }
    },
    [addFeedComment]
  );

🏷 출처

React 타입스크립트의 개념과 사용법 정리

profile
배움은 즐거워 ~(*ૂ❛ᴗ❛*ૂ)

0개의 댓글