똑같은 삽질은 2번 하지 말자

Typescript 본문

Typescript

Typescript

곽빵 2021. 7. 4. 15:43

배우기에 급급해서 타입스크립트를 왜 쓰는지는 알아도 어떻게 해야 잘 활용할 수 있을까? 에 대한 개념은 확실하지 않은것 같다.

그래서 여기에서의 글은 내가 타입스크립트를 좀더 잘 활용할 수 있을 팁들을 적어나가고자 한다.

(캡틴판교 장기효님의 강의를 보면서!) 마냥 쓰는게 아니라 생각하고 쓰자..!


상품목록을 보여주는 화면을 구현해야하는 상황이다.

상품목록

위의 사진처럼 상품목록들이 들어오면 우리는 상품에대한 type을 정의한다.

type Product = {
  id: number;
  name: string;
  price: number;
  brand: string;
  stock: number;
}

function fetchProducts(): Promise<Product[]> {

}

하지만 저 화면중 하나의 상품을 클릭해서 들어오면 그 상품에관해서만 정보를 뿌려주는 화면을 구현한다고 하면,

Product타입을 그대로 가져다 쓸 수는 없을 것이다.(속성이 추가되거나 삭제될 수 있기때문)

 

상품 상세정보 화면

그럼 타입을 한개 더 선언해야하는데..

(*최대한 구체적으로 타입을 정의하고 타입을 어떻게 좀더 줄일 수 있거나 재활용한다는 관점보다는 일단

자바스크립트에 타입을 입혀서 오류가 발생하지 않게하는 타입스크립트의 장점들을 가져가자는 관점이 더 중요하다. )

(그렇게 장점을 최대한 살린다는게 보장이되면 타입을 줄이거나 재활용하는것을 생각하자.)

 

그렇다면 이하의 코드를 추가해 ProductDetail이라는 타입을 하나 더 선언하게 될것이다.(Pick 말고도 다른 문법도 많다.)

type ProductDetail = Pick<Product, 'id' | 'name' | 'price'>

function displayProductDetail(shoppingItem: ProductDetail) {

}

이렇게 타입을 한개 더 선언하지만, 선언하지 않고도 그대로 활용할 수 있다.

 

요로코롬 불필요한 타입코드들을 조금이나 줄일 수 있다.

function displayProductDetail(shoppingItem: Pick<Product, 'id' | 'name' | 'price'>) {

}

이번에 상품의 정보를 업데이트 해야하는 상황이라 치면, 업데이트에는 상품안의 정보중 들어가는 정보도있고,

갱신이 필요없는 정보도 있을것이다. 그럼 되도록 모두다 Optional로 만들어줘야하는데 어떻게해야 깔끔하게 만들까

라고 하면 , Partial이라는 유틸리티 타입을 활용하면 된다.

 

Partial

 

전부 Optional로 바꿔준다...

Partial 실제 구현 (feat. Mapped Type)

Partial 구현 과정을 풀어서 적어보았다.

여기서 맵드타입이 등장했는데 맵드타입이란 뭔가?

 

맵드 타입이란 기존에 정의되어 있는 타입을 새로운 타입으로 변환해 주는 문법을 의미합니다.

마치 자바스크립트 map() API 함수를 타입에 적용한 것과 같은 느낌


자바스크립트 코드에 타입스크립트를 적용할 때 주의해야 할 점

  • 기능적인 변경은 절대 하지 않을 것
  • 테스트 커버리지가 낮을 땐 함부로 타입스크립트를 적용하지 않을 것
  • 처음부터 타입을 엄격하게 적용하지 않을 것 (점진적으로 strict 레벨을 증가)

타입스크립트의 눈에띄는 가장 큰 이점?

이거는 타입스크립트에 입문했을때 부터 들었던 이야기이지만, 어떤 API를 이용할 때,

어떤 데이터들이 오는지 그 API를 구축한 사람이 아니면 자세히 알기 어렵다.(구축했다해도 시간지나면 까먹죠)

하지만 타입스크립트로 한번 확실하게 정의해두면 설령 프로젝트에 중간에 투입되는 사람일지라도

해당 API에서 어떤 데이터들이 오고 어떤 타입인지 명확하게 파악할 수 있기 때문에

에러, 개발, 유지및 보수측면에서도 좋은 효과를 기대할 수 있다.

 

예를들면 이하의 정보를 가져오는 API가 있다.

코로나 정보 관련 API

해당 API를 직접 쓰고있는곳 에서도 어떤 데이터가 올지 전혀 알 수 없다.

JS DOC으로 타입스크립트의 효과를 내는중,,,(// @ts-check을 코드위에 기입하면 ts lang server가 돈다)

그래서 간단하게 JSDOC으로 타입스크립트의 효과를 내서 타입을 정의해 보면

이게 얼마나 사람 살리는 기능일지 겪어본 사람들은 알것이다.

API와 데이터를 주고 받을때, 에러가 나면 안의 객체를 하나하나 뒤져보면서 잘못왔거나 값이 안들어갔거나 

이름이 틀려서 아예 담기질않았다던가등등 수많은 에러로 시간 날리는게 다반사인데, 타입스크립트로 전부 커버 가능하다..

 

타입스크립트 기본설정 파일


npm으로 라이브러리들을 관리하고 있다면 타입스크립트를 적용하는데 수월하지만,

cdn으로 외부라이브러리를 참조하고 있는 경우에는 자바스크립트의 모듈의 개념을 탑재해서 외부라이브러리를 인식시켜야 한다.

외부라이브러리 cdn으로 끌고오는중

axios 는 정말 잘 관리되고 있는 라이브러리(이미 타입정의 잘 되있는)이기 때문에 npm i axios를 한뒤

import를 해주는것만으로 에러들이 사라지는데, 

다른 오픈소스 라이브러리들을 사용할 때가 문제이다. (type이 정의안된 라이브러리들)

chart.js 의 타입이 없다 그러니깐 @types(DefinitelyTyped)에서 타입을 받아라

 

그럴땐, DefinitelyTyped 을 이용하자(라이브러리들의 Type이 정의된 곳)

https://github.com/DefinitelyTyped/DefinitelyTyped

 

DefinitelyTyped/DefinitelyTyped

The repository for high quality TypeScript type definitions. - DefinitelyTyped/DefinitelyTyped

github.com

 

그럼 @type에도 없으면 어떻게 해야할까?

declare type파일을 만들어서 그걸 읽어들이게하면 된다.

types 폴더 / 타입이 정의안된 라이브러리 이름의 폴더 /  index.d.ts


타입 단언 시 주의해야 할 점

어떤 하나의 아이템이 있고 그 타입속성으로 id, name이 있다.

위의 코드처럼 item1은 그냥 오브젝트라 선언하고 타입속성들을 넣지 않으면 에러가 생긴다.

 

하지만, 타입단언으로 이 item1은 item형태이다 라고 하면

에러가 나지 않는다.

실무에서는 item 같은 타입, 인터페이스들은 다른 파일들로 모듈화가 되어있기때문에,

우리가 item1을 저렇게 타입단언을하고 안에 값을 넣지않아도 계속~~~에러가 나지않는다.

개발하는 입장에서 이게 타입을 확정할 수 있는경우에 타입단언을 사용해도 되지만,

모든 로직에 타입단언을 사용해 버리면 우리가 미처 보지못한 곳에서 에러가 나올 수 있는 가능성이 생기는것이다.

타입단언으로 해야 유연하게 되는 경우가 있지만, 타입단언은 되도록 주의해서 써야한다는걸 새겨두자.

 

feat. Optional Chaining( 우리가 possibly null 에러를 만날때 자주쓰는 옵셔날 체이닝 까먹을까봐 코드로 써놓음)

recoveredList?.appendChild(li);
    
// ? (Optional Chaining) 을 코드로 쓰면
if (recoveredList === null || recoveredList === undefined) {
  return;
} else {
  recoveredList.appendChild(li)
}
Comments