이펙티브 타입스크립트(5)

남자김용준·2021년 11월 7일

아이템21. 타입 넓히기

타입스크립트는 종종 지정된 단일 값을 가지고 할당 가능한 값들의 집합을 유추해내야 한다. 이러한 과정을 '넓히기'라고 한다.

const, 타입 구문, 문맥, as const 사용에 익숙해져야 한다.

let x= 'x'; // string으로 추론
const x = 'x'; // 타입이 'x'

const v = {
  x:1,
}
v.x = 3 // 정상
v.x = '3' // error
v.y = 5 // error

const v1 = {
  x : 1,
  y : 2
} // 타입은 { x : number; y : number; }

const v2 = {
  x : 1 as const,
  y : 2
} // 타입은 { x : 1; y : number; }

const v3 = {
  x : 1,
  y : 2
} as const
// 타입은 { readonly x : 1; readonly y : 2; }

아이템22. 타입 좁히기

타입 좁히기는 타입스크립트가 넓은 타입으로부터 좁은 타입으로 진행하는 과정을 말한다.

const el = document.getElementById('foo'); // 타입이 HTMLElement | null
if(el){
  el // 타입이 HTMLElement
  el.innerHTML = 'Party'.blink();
} else {
  el // 타입이 null
  alert('No element')_;
}

분기문 외에도 여러 종류의 제어 흐름을 살펴보며 타입스크립트가 타입을 좁히는 과정을 이해해야 한다.

태그된/구별된 유니온과 사용자 정의 타입 가드를 사용하여 타입 좁히기 과정을 원할하게 만들 수 있다.

instanceof, Array.isArray, 태그된 유니온 패턴, 사용자 정의 타입 가드

아이템23. 한꺼번에 객체 생성하기

객체의 타입 추론을 위해서 속성을 제각각 추가하지 말고 한꺼번에 만들어야 한다.

안전한 타입으로 속성을 추가하려면 객체 전개 ({...a,...b})를 사용하면 된다.

객체에 조건부로 속성을 추가하는 방법을 익혀야 한다.

declare let hasDates : boolean;
const nameTitle = {name:'TEST', title:'TITLE'};
const pharaoh = {
  ...nameTitle,
  ...(hasDates ? {start: -123, end: -321} : {})
}

cosnt pharaoh : {
  start : number;
  end : number;
  name : string;
  title: string;
} | {
  name: string;
  title: string;
}

아이템24. 일관성 있는 별칭 사용하기

const test = {name:'TEST',location:[1,2]};
const loc = test.location;
loc[0] = 0;
test.location // [0,2]

위의 loc을 별칭이라고 한다. 별칭의 값을 변경하면 원래 속성값에서도 변경된다.

별칭은 타입스크립트가 타입을 좁히는 것을 방해한다. 따라서 변수에 별칭을 사용할 때는 일관되게 사용해야 한다.

interface Coordinate {
  x : number;
  y : number;
}

interface BoundingBox {
  x : [number,number];
  y : [number,number];
}

interface Polygon {
  exterior : Coordinate[];
  holes : Coordinate[];
  bbox?: BoundingBox;
}
function isPointInPolygon(polygon,: Polygon, pt: Coordinate){
  const box = polygon.bbox;
  if(polygon.bbox){
    if(pt.x < box.x[0] || pt.x > box.x[1]) ||
      // ~~~ ~~~ box 객체가 undefined일 수 있음
      // if문에서 타입을 좁힌 건 bbox / box 객체의 타입을 좁히지 않음
  }
};
function isPointInPolygon(polygon,: Polygon, pt: Coordinate){
  const { bbox } = polygon.bbox;
  if(bbox){
    const {x,y} = bbox;
    if(pt.x < x[0] || pt.x > x[1]) ||
  }
}
  

비구조화 문법을 사용해서 일관된 이름을 사용하는 게 좋다.

함수 호출이 객체 속성의 타입 정제를 무효화할 수 있다는 점을 주의해야 한다. 속성보다 지역 변수를 사용하면 타입 정제를 믿을 수 있다.

아이템25. 비동기 코드에는 콜백 대신 async 함수 사용하기

콜백보다는 프로미스를 사용하는 게 코드 작성과 타입 추론면에서 유리하다.

가능하면 프로미스를 생성하기보다는 async와 await을 사용하는 게 좋다.

어떤 함수가 프로미스를 반환한다면 async로 선언하는 게 좋다.

profile
frontend-react

0개의 댓글