1. 조건적인 타입 선언을 위한 문법들

extends

제약 조건으로서 사용되는 extends

타입스크립트에서 제공하는 내장 제네릭 Pick 은 다음과 같이 구현할 수 있고, 사용된다.

type MyPick<T, U extends keyof T> = {
  [key in U]: any;
}

type Person = {
  name: string;
  age: number;
  address: string;
}

type PrivatePerson = MyPick<Person, 'name'>;

여기서, extends가 사용된 타입 정의는 어떻게 해석할 수 있을까? 종종 머리가 복잡해지는 구문이다.

T extends U

타입 시스템을 집합으로 표현했을때, 'T는 U보다 작다.' 혹은 'T는 U의 부분집합이다.' 로 해석할 수 있다. 즉, T의 범위를 U로 제한하는 제약 조건을 둔 셈이다.

U extends keyof T

다시 Pick에서 사용된 extends의 구문을 보면, 'U는 T 객체의 키 집합으로 제한한다.' 혹은 'U는 T객체의 키 값의 부분 집합이다.'로 해석할 수 있다.

조건부로 사용되는 extends

타입 시스템에서 입력의 타입을 기반으로 출력의 타입을 결정할 수 있도록 타입 간의 관계를 열어두었다. 바로 extends를 조건부로 사용할 수 있는데, 해석은 제약 조건과 같지만, 마치 'T는 U의 부분집합인가?'를 묻는 의문문으로 사용된다.

false는 boolean의 부분 집합인가?, 'false'는 boolean의 부분 집합인가? 답은 각각 true, false를 얻어낼 수 있다. 조건에서 얻어진 참, 거짓의 결과를 삼항 연산자와 함께 조건부로서 출력 타입을 결정할 수 있다.

T에서 U에 할당할 수 있는 타입을 제외하는 내장 제네릭 Exclude<T, U>를 예시로 들어보자. 유니온된 타입 중 하나인 'number는 number의 부분집합인가?' 에 참이기 때문에 never을 반환한다.

Infer

inferextends의 조건식에서 사용되는 타입을 꺼내 담고, 참으로 평가될때 전개되는 구문에서 사용할 수 있다. 타입스크립트 엔진이 런타임 상황에서 타입을 추론할 수 있도록 열어두고, 조건이 참이면 infer U 구문의 U 타입을 할당, 거짓이면 never를 할당하여 무시한다.

T에 할당된 타입이 함수일때, 해당 함수의 파라미터를 튜플 타입으로 반환하는 내장 제네릭 Parameters<T>를 예시로 들어보자. ParametersT로서 가능한 타입을 함수로 제한하고, 제한된 함수 타입에 부합하는지에 대한 참 조건에서 U로 명명된 타입을 사용한다.

이해를 돕기 위해 또 다른 예시를 살펴보자. 가령 Promise와 같이 래핑하는 타입 내부의 타입을 구하고 싶다면 어떻게 할 수 있을까? 재귀적으로 Promise 타입을 벗겨내서 내부 타입을 추론할 수 있다.

Last updated