TypeScript 의 infer 를 통해 타입 추론을 더욱 잘 사용하는 법
타입스크립트의 예약어 중 하나인 infer 를 통해 컨디셔널 타입과 함께 타입 추론을 극한까지 활용할 수 있다.
infer
1
2
3
type El<T> = T extends (infer E)[] ? E : never;
type Str = El<string[]>; // type Str = string
type NumOrbool = El<(number | boolean)[]>; // type NumOrBool = number | boolean
El 타입에서 infer 를 활용한 예시로, 배열이 있을 때 그 요소의 타입을 얻어내는 상황이다. E
라는 변수 하나가 있는데, 이는 타입 변수(type variable)로 infer
예약어와 함께 사용하면 된다.
컨디셔널 타입의 참 부분에서만 사용이 가능하다. 거짓 부분에서 사용하면 에러가 발생한다.
1
type El<T> = T extends (infer E)[] ? never : E;
다음은 매개변수, 생성자 매개변수, 인스턴스의 타입을 추론하는 타입이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type MyParaemters<T> = T extends (...args: infer P) => any ? P : never;
type MyConstructorParameters<T> = T extends abstract new (...args: infer P) => any ? P : never;
type MyreturnType<T> = T extends (...args: any) => infer R ? R : any;
type MyInstance<T> = T extends abstract new (...args: any) => infer R ? R : any;
type P = MyParameter<(a: string, b: number) => string> // type P = [a: string, b: number], 튜플임.
type R = MyReturnType<(a: string, b: number) => string> // type R = string
type CP = MyConstructorParameter<new (a: string, b: number) => {}> // type CP = [a: string, b: number], 튜플임.
type I = MyInstance<new (a: string, b: number) => {}> // type I = {}
1
2
3
4
5
6
7
8
9
type Union<T> = T extends { a: infer U, b: infer U } ? U : never;
type Result = Union<{ a: 1 | 2, b: 2 | 3}>; // type Result1 = 1 | 2 | 3
type InterSection<T> = T extends {
a: (pa: infer U) => void,
b: (pb: infer U) => void
} ? U : never;
type Result2 = Intersection<{ a(pa: 1 | 2): void, b(pb: 2 | 3): void }>; // type Result2 = 2
Union<T>
타입에서는 a 와 b 속성의 타입을 모두 U 타입 변수로 선언했다. Union 타입을 사용할 땐 a 에 1 | 2, b 에 2 | 3 타입을 넣었다. 그 결과는 a 와 b 의 유니온인 1 | 2 | 3
이 나왔다.
반대로, Intersection<T>
에서는 a 와 b 가 메서드다. 메서드의 매개변수 pa, pb 에 같은 U 타입 변수를 선언했음에도 이번에는 a 와 b의 교집합인 2 가 나왔다.
이는 공변성, 반공변성에 대해 이해야하는 내용인데 추후에 다시 다뤄보도록 하자.
This post is licensed under CC BY 4.0 by the author.