코딩/한 입 크기로 잘라먹는 타입스크립트
[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 타입을 할당하면 분산적인 조건부 타입으로 조건부 타입이 업그레이드 되기 때문이다.
- 타입 변수에 할당한 유니온 타입 내부의 모든 타입이 분리된다.
- StringNumberSwitch<number>
- StringNumberSwitch<string>
- 분산된 각 타입의 결과를 모아 유니온 타입으로 묶는다.
- 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타입으로 설정한다.
- 유니온 타입 분리
- Exclude<number, string>
- Exclude<string, string>
- Exclude<boolean, string>
- 분리된 타입 계산
- T = number, U = string 일 때 T는 U의 서브타입이 아님 => number
- T = string, U = string 일 때 T는 U의 서브타입 => never
- T = boolean, U = string 일 때 T는 U의 서브타입이 아님 => boolean
- 계산된 타입들을 모두 유니온으로 묶기
- 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 타입으로 설정한다.
- 유니온 타입 분리
- Extract<numebr, string>
- Extract<string, string>
- Extract<boolean, string>
- 분리된 타입 계산
- T = number, U = string 일 때 T는 U의 서브타입이 아님 => never
- T = string, U = string 일 때 T는 U의 서브타입 => string
- T = boolean, U = string 일 때 T는 U의 서브타입이 아님 => never
- 계산된 타입들을 모두 유니온으로 묶기
- 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