Post

타입스크립트 확장하기 - 예시

우아한 타입스크립트 도서의 일부 내용을 정리한 포스트입니다.

타입 확장

쇼핑몰 어플을 사용하다보면 카테고리 메뉴는 카테고리 이미지와 카테고리 이름으로 이루어져있다.

<이미지> 이것을 `ICategoryMenu`라는 이름을 가지는 인터페이스로 작성해보면 다음과 같다. 여기서 `I`는 interface로 작성된 타입이라고 명시해줄 때 사용하는 방법이다. ```ts interface ICategoryMenu { name: string; image: string; } ``` 그리고 작성한 인터페이스를 사용해서 다음과 같은 컴포넌트를 작성할 수 있다. ```tsx function CategoryMenu(){ const categoryMenuList: ICategoryMenu[] : [ {name:"세일",image:"세일아이콘.png"}, {name:"이벤트",image:"이벤트아이콘.png"} ] return (
    {categoryMenuList.map((menu)=>(
  • <img src={menu.image} />

    {menu.name}

    ))}
) } ``` 이렇게 작성된 기본 카테고리 메뉴에 다음과 같은 요구사항이 추가되었다. > 1. 특정메뉴에 마우스를 호버하면 아이콘이 움직인다. (gif) > 2. 특정메뉴는 이미지 대신 텍스트가 노출된다. (text) 기본 타입에 위와 같은 요구사항을 추가하여 타입을 확장하는 방법은 두가지가 있다. ### 첫번째, 타입 안에 속성 추가 ```ts interface ICategoryMenu { name: string; image: string; gif?: string; text?: string; } ``` `ICategoryMenu`에 옵셔널로 속성을 추가하였다. 기본 메뉴만 사용할 때에도, gif 이미지를 사용할 때에도, 이미지 대신 텍스트만 사용할 때에도 `ICategoryMenu[]`을 사용하면 된다. ```ts const categoryMenuList: ICategoryMenu[] = [...] const gifImgCategoryMenuList: ICategoryMenu[] = [...] const onlyTextCategoryMenuList: ICategoryMenu[] = [...] ``` 하지만 `onlyTextCategoryMenuList` 배열의 각 속성에 접근할 때 다음과 같은 문제가 발생한다. ```ts onlyTextCategoryMenuList.map((menu) => menu.text); // TypeError! Cannot read properties of undefined ``` `onlyTextCategoryMenuList` 배열 안 요소에 `text` 속성이 있지만 옵셔널(`?`)을 사용했기 때문에 값이 `undefined`일 수도 있어서 발생하는 타입오류이다. ### 두번째, 타입 확장하기 기본 타입인 `ICategoryMenu`을 `extends`를 사용하여 요구 사항에 맞게 타입을 확장하여 사용하는 방법이다. ```ts interface ICategoryMenu { name: string; image: string; } interface GifImgCategoryMenu extends ICategoryMenu { gif: string; } interface OnlyTextCategoryMenu extends ICategoryMenu { text: string; } ``` 확장한 타입들을 사용하여 각 메뉴목록의 타입을 지정해보면 다음과 같다. 기본 메뉴만 사용할 때에는 기본 타입인 `ICategoryMenu`을, gif 이미지를 사용할 때에는 `GifImgCategoryMenu`을, 이미지 대신 텍스트만 사용할 때에는 `OnlyTextCategoryMenu[]`을 사용하면 된다. ```ts const categoryMenuList: ICategoryMenu[] = [...] const gifImgCategoryMenuList: GifImgCategoryMenu[] = [...] const onlyTextCategoryMenuList: OnlyTextCategoryMenu[] = [...] ``` 첫번째 방법처럼 `onlyTextCategoryMenuList` 배열의 각 속성에 접근해보면, 첫번째 방법과는 다르게 오류가 발생하지 않는다. ```ts onlyTextCategoryMenuList.map((menu) => menu.text); ``` `onlyTextCategoryMenuList`에는 기본 타입의 name, image 그리고 text의 속성을 가지기때문에 오류가 발생하지 않는다. 또한 `gifImgCategoryMenuList`에서 text 속성에 접근하면, 타입오류가 발생한다. `gifImgCategoryMenuList`에는 기본 타입의 name, image 그리고 gif 속성만 가지기 때문에 오류가 발생한다. ```ts gifImgCategoryMenuList.map((menu) => menu.text); // Property 'text' does not exist on type. ``` ## 결론 기본 타입에 속성을 계속 추가해서 사용하는 것보다 기능에 맞도록, 요구사항에 맞도록 타입을 확장하여 사용하는 것이 더 효율적이며 버그를 줄일 수 있다. 출처 - 우아한 타입스크립트 with 리액트
This post is licensed under CC BY 4.0 by the author.