// 재귀적으로 배열의 요소 내부 접근해서 요소 타입을 겟
type ElementType<T> = T extends any[] ? ElementType<T[number]> : T;
타입 인수로 사용하는 것은 불가능
이 경우는 타입 인수를 쓰지 않는 방식으로 수정해야함
type T = number | string | Record<string, T>; // error
type T = number | string | { [key: string]: T };
재귀 타입도 맥시멈 콜스택과 비슷한 에러 발생 가능
재귀 타입을 선언할 때가 아닌 사용할 때 에러가 발생
type InfiniteRecur<T> = { item: InfiniteRecur<T> };
type Unwrap<T> = T extends { item: infer U } ? Unwrap<U> : T;
type Result = Unwrap<InfiniteRecur<any>>; // error
// Unwrap<{ item: { item: { item: 'hi' } } } > -> hi
// InfiniteRecur 타입은 무한하여 Unwrap 타입은 유한한 시간 안에 InfiniteRecur 타입을 처리할 수 없음##복잡한 구조도 쉽게 표현 가능
type Reverse<T> = T extends [...infer L, infer R] ? [R, ...Reverse<L>] : []
매개변수 순서를 바꾸는 타입 (매개변수는 반공변성)
// 내가 첫 시도한 타입인데...
type ReverseParams<T> = T extends (...infer LP, infer RP) => any
? [RP, ...ReverseParms<LP>] : []
// 정답
type FlipArguments<T> = T extends (...args: infer A) => infer R
? (...args: Reverse<A>) => R
: never
// 반환값과 매개변수의 타입을 추론한 뒤, 매개변수의 Reverse 타입 적용,
// A는 이미 매개변수의 튜플 상태이므로 바로 Reverse 타입 적용 가능
type Flipped = FlipArguments<(a: string, b: number, c: boolean) => string>;