타입스크립트 (11) 조건부 타입

김태완·2024년 11월 21일
post-thumbnail

조건부 타입

  • 조건부 타입은 extends삼항 연산자를 이용해 조건에 따라 각각 다른 타입을 정의하도록 돕는 문법이다.
  • 조건부 타입은 위 코드처럼 number extends string ? 과 같은 조건식이 있고, 이 조건이 참이라면 ? 우측의 타입인 Number 타입이 결과가 되고 아니라면 : 우측의 타입인 String 타입이 결과가 된다.
  • 위 조건부 타입의 조건식 number extends string은 number 타입이 string 타입의 서브타입이 아니기 때문에 거짓이 되고, 그 결과 타입 A는 string 타입이 된다.
  • 이번엔 조건식에 객체 타입을 사용해보자.
  • B는 ObjB는 ObjA의 서브 타입 이므로 조건식이 참이되어 number 타입이 된다.
    • ObjB 타입이 ObjA 타입을 확장하느냐?

제네릭 조건부 타입

  • 조건부 타입은 제네릭과 함께 사용할 때 그 위력이 극대화 된다.
  • 다음은 타입변수에 Number 타입이 할당되면 String 타입을 반환하고, 그렇지 않다면 Number 타입을 반환하는 조건부 타입이다.
    • varA는 T에 number 타입을 할당한다. 그 결과 조건식이 참이 되어 string 타입이 된다.
    • varB는 T에 string 타입을 할당한다. 그 결과 조건식이 거짓이 되어 number 타입이 된다.

분산적인 조건부 타입

  • 조건부 타입 문법에 따라 변수 c의 타입은 number | string은 number의 서브타입이 아니므로 조건식이 거짓이 되어 number가 될거라고 예상할 수 있다.
  • 그러나 변수 c는 string | number 타입으로 정의된다. 왜?
  • 이유는 조건부 타입의 타입 변수에 Union 타입을 할당하면 분산적인 조건부 타입으로 조건부 타입이 업그레이드 되기 때문이다.
  • 분산적인 조건부 타입은 다음과 같이 동작한다.
  • 타입 변수에 할당한 Union 타입 내부의 모든 타입이 분리된다.
  • 따라서 StringNuberSwitch<number | string> 타입은 다음과 같이 분산된다.
    • StringNumberSwitch<number>
    • StringNumberSwitch<string>
  • 그리고 다음으로 분산된 각 타입의 결과를 모아 다시 Union 타입으로 묶는다. 결과 : number | string

Exclude 조건부 타입 구현하기

  • 분산적인 조건부 타입의 특징을 이용하면 매우 다양한 타입을 정의할 수 있다.
  • 예를 들어 Union 타입으로부터 특정 타입만 제거하는 Exclude(제외하다) 타입을 다음과 같이 정의할 수 있다.
  • 위 코드는 다음의 흐름으로 동작한다.
    • Union 타입이 분리된다.
      • Exclude<number, string>
      • Exclude<string, string>
      • Exclude<boolean, string>
    • 각 분리된 타입을 모두 계산한다.
      • T = number, U = string 일 때 number extends string 은 거짓이므로 결과는 number
      • T = string, U = string 일 때 string extends string 은 참이므로 결과는 never
      • T = boolean, U = string 일 때 boolean extends string 은 거짓이므로 결과는 boolean
    • 계산된 타입들을 모두 Union으로 묶는다.
      • 결과 : number | never | boolean
    • 계산 결과 타입 A는 number | never | boolean 타입으로 정의된다.
    • 그런데 여기서 공집합을 의미하는 never 타입은 Union으로 묶일 경우 사라진다. 그 이유는 공집합과 어떤 집합의 합집합은 그냥 원본 집합이 되기 때문이다.
    • 따라서 최종적으로 타입 A는 number | boolean 타입이 된다.
  • 이렇게 대괄호를 주면 타입의 분산을 방지할 수 있다.

infer

  • infer는 조건부 타입 내에서 특정 타입을 추론하는 문법이다.
  • infer는 다음과 같이 특정 함수 타입에서 반환값의 타입만 추출하는 특수한 조건부 타입인 ReturnType을 만들 때 이용할 수 있다.
  • 조건식 T extends () => infer R에서 infer R은 이 조건식을 참이 되도록 만들 수 있는 최적의 R 타입을 추론하라는 의미이다. (그냥 R로 보면된다.)
  • 따라서 A 타입을 계산할 때의 위 코드의 흐름은 다음과 같다.
profile
중고

0개의 댓글