코딩/한 입 크기로 잘라먹는 타입스크립트

[TypeScript] 분산적인 조건부 타입

김기지 2023. 9. 25. 21:19

🐶 분산적인 조건부 타입

유니온 타입과 함께 사용할 때 조건부 타입이 분산적으로 동작하는 문법

 

type StringNumberSwitch<T> = T extends number? string : number;

let a: StringNumberSwitch<number>;
// string

let b: StringNumberSwitch<string>;
// number

let c: StringNumberSwitch<number | string>;
// string | number
// T는 number 타입의 슈퍼타입이 됨 -> 거짓이 되므로 number 타입이 되어야함
// 하지만 c는 string | number 유니온 타입이 됨
  • a는 number 타입의 인자를 넘김 -> 조건이 참이므로 string 타입
  • b는 string 타입의 인자를 넘김 -> 조건이 거짓이므로 number 타입
  • c는 number | string 유니온 타입의 인자를 넘김 -> 조건이 거짓이므로 number 타입이 되어야 함

그러나 변수 c는 string | number 타입으로 정의된다. 

이는 조건부 타입의 타입 변수에 Union 타입을 할당하면 분산적인 조건부 타입으로 조건부 타입이 업그레이드 되기 때문이다.

  1. 타입 변수에 할당한 유니온 타입 내부의 모든 타입이 분리된다.
    • StringNumberSwitch<number>
    • StringNumberSwitch<string>
  2. 분산된 각 타입의 결과를 모아 유니온 타입으로 묶는다.
    • number | string

 

type StringNumberSwitch<T> = T extends number? string : number;

let d: StringNumberSwitch<boolean | number | string>;
// 1단계
// StringNumberSwitch<boolean> |
// StringNumberSwitch<number> |
// StringNumberSwitch<string>

// 2단계
// number |
// string |
// number

// 결과
// number | string

 

 

 

 

 

 

 

예제 1. 유니온 타입에서 특정 타입만 제거하는 타입 구현

type Exclude<T, U> = T extends U? never : T;
//T가 U의 서브타입이면 never, 아니면 T

type A = Exclude<number | string | boolean, string>;
// number | boolean

Exclude 타입은 T가 U의 서브타입이라면 never 아니라면 T타입으로 설정한다.

  1. 유니온 타입 분리
    • Exclude<number, string>
    • Exclude<string, string>
    • Exclude<boolean, string>
  2. 분리된 타입 계산
    • T = number, U = string 일 때 T는 U의 서브타입이 아님 => number
    • T = string, U = string 일 때 T는 U의 서브타입 => never
    • T = boolean, U = string 일 때 T는 U의 서브타입이 아님 => boolean
  3. 계산된 타입들을 모두 유니온으로 묶기
    • number | never | boolean 이지만 never는 공집합으로 합집합을 하게 되면 원본 집합이 됨 => number | boolean

 

 

 

 

 

 

 

예제 2. 유니온 타입에서 특정 타입만 가져오기

 

type Extract<T, U> = T extends U? T : never;

type B = Extract<number | string | boolean, string>;
// string

Extract 타입은 T가 U의 서브타입이라면 T로 아니라면 never 타입으로 설정한다.

  1. 유니온 타입 분리
    • Extract<numebr, string>
    • Extract<string, string>
    • Extract<boolean, string>
  2. 분리된 타입 계산
    • T = number, U = string 일 때 T는 U의 서브타입이 아님 => never
    • T = string, U = string 일 때 T는 U의 서브타입 => string
    • T = boolean, U = string 일 때 T는 U의 서브타입이 아님 => never
  3. 계산된 타입들을 모두 유니온으로 묶기
    • never | string | never => string

 

 

 

 

 

 

📍 Tip. 분산적으로 작동하지 않도록 하는 방법

조건부 타입이 분산적으로 작동하지 않길 원하는 경우에는 extends의 양 옆을 []로 묶어주면 분산적으로 동작하지 않는다.

 

// Tip
// 조건부 타입이 분산적으로 작동하지 않도록 하려면
// extends의 양 옆을 []로 묶어줌
type StringNumberSwitch2<T> = [T] extends [number]? string : number;

let e: StringNumberSwitch2<boolean | number | string>; // number

 

 

 

 

 

 


🔗 타입스크립트 강의

 

한 입 크기로 잘라먹는 타입스크립트(TypeScript) - 인프런 | 강의

문법을 넘어 동작 원리와 개념 이해까지 배워도 배워도 헷갈리는 타입스크립트 이제 제대로 배워보세요! 여러분을 타입스크립트 마법사🧙🏻‍♀️로 만들어드립니다., 프론트엔드의 피할 수

www.inflearn.com

 

728x90