TS스터디 이펙티브 item22~23

온호성·2023년 4월 10일
0

😵item 22 타입 좁히기

ts에서 타입 좁히기는 변수가 가질 수 있는 타입을 제한하여 더 구체적인 타입으로 좁히는 것을 말한다. 타입 좁히기는 주로 조건문이나 반복문 등에서 변수의 타입을 추론할 때 사용된다.

예를 들어, 아래와 같이 x 변수를 선언하고, if 문에서 x 변수의 타입을 좁히는 경우,

let x: string | number = "hello";

if (typeof x === "string") {
  // x는 이 블록 내에서 string 타입으로 추론된다.
  console.log(x.toUpperCase());
} else {
  // x는 이 블록 내에서 number 타입으로 추론된다.
  console.log(x.toFixed(2));
}

x 변수의 타입을 string 또는 number로 제한하여, if문 내에서 각각 다른 타입으로 사용할 수 있게 된다. 이렇게 타입을 좁히면, 코드 안정성을 높일 수 있다.

ts에서 타입 좁히기를 할 때는 주로 typeof, instanceof, in, null 체크 등을 사용한다. 이외에도, 함수의 반환 타입이나 인자 타입에 따라 변수의 타입을 추론하는 것도 가능하다.

null 체크

타입 체커는 일반적으로 이런 조건문에서 타입 좁히기를 잘하지만, 타입 별칭이 존재한다면 그러지 못할 수도 있다.

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

instanceof 사용

function contains(text:string, search:string|RegExp){
  if (search instanceof RegExp) {
    search; // 타입이 RegExp
    return !!search.exec(text);
  }
  search // 타입이 string
  return text.includes(search);
}

속성 체크

interface A { a: number }
interface B { b: number }
function pickAB(ab: A | B) {
  if ('a' in ab) {
    ab // Type is A
  } else {
    ab // Type is B
  }
  ab // Type is A | B
}

-요약-

  • 분기문 외에도 여러 종류의 타입 좁히기 방법에 대해 이해
  • 태그/구별된 유니온과 사용자 정의 타입 가드의 사용법과 타입 좁히기에 대해 이해

🥳item 23 한꺼번에 객체 생성하기

변수의 값은 변경될 수 있지만, ts의 타입은 일반적으로 변경되지 않는다.
객체를 생성할 때는 속성을 하나씩 추가하기 보다는 여러 속성을 포함해서 한꺼번에 생성해야 타입 추론에 유리하다.

const pt = {}
pt.x = 3
// ~ Property 'x' does not exist on type '{}'
pt.y = 4
// ~ Property 'y' does not exist on type '{}'

pt 타입은 {} 을 기준으로 추론되기 때문에 오류가 발생한다.
이런 문제는 객체를 한번에 정의하면 해결할 수 있다.

interface Point {
  x: number
  y: number
}
const pt = {
  x: 3,
  y: 4,
} // OK

작은 객체들을 조합해서 큰 객체를 만들어야 하는 경우에는 스프레드 연산자 ... 를 사용하여 한꺼번에 만들 수 있다.

const pt = { x: 3, y: 4 }
const id = { name: 'Pythagoras' }

const namedPoint = { ...pt, ...id }
namedPoint.name // OK, type is string

객체 전개 연산자로 하나의 속성을 조건부 연산으로 추가하면 타입이 선택적 속성을 가진것으로 추론된다. 그러나 여러개의 속성을 추가하면 이는 유니온으로 추론된다. 이 경우 선택적 필드 방식으로 표현하려면 아래와 같이 헬퍼 함수를 사용하자.
(헬퍼 함수는 작은 기능을 수행하는 함수로, 코드의 재사용성을 높이고 가독성을 향상시키는 데 도움을 준다.)

 // 헬퍼함수
const addOptional = <T extends object, U extends object>(a: T, b: U | null): T & Partial<U> => {
  return { ...a, ...b };
};

declare let hasDates: boolean;
const nameTitle = { name: 'Khufu', title: 'Pharaoh' };
const pharaoh = addOptional(nameTitle, hasDates ? { start: -2589, end: -2566 } : null);
pharaoh.start // 정상, 타입이 number | undefined

가끔 객체나 배열을 변환해서 새로운 객체나 배열을 생성하려는 경우 내장된 함수형 기법 또는 로대시 같은 유틸리티 라이브러리를 사용하는 것이 ‘한꺼번에 객체 생성하기' 관점에서 보면 옳다.

-요약-

  • 속성을 제각각 추가하지 말고 한번에 추가하는 것이 더 좋고, 안전한 타입으로 속성을 추가하려면 객체 전개({...a,...b})를 사용하면 된다.
  • 객체에 조건부로 속성을 추가하는 방법을 익히기

0개의 댓글

관련 채용 정보