kakasoo

TupleToUnion 타입 정의하기 본문

프로그래밍/TypeScript

TupleToUnion 타입 정의하기

카카수(kakasoo) 2023. 2. 17. 00:45
반응형

https://github.com/type-challenges/type-challenges/blob/main/questions/00010-medium-tuple-to-union/README.md

type Arr = ['1', '2', '3']

type Test = TupleToUnion<Arr> // expected to be '1' | '2' | '3'

answer

type TupleToUnion<T extends any[]> = any
type TupleToUnion<T extends any[]> = T[number];

답을 먼저 제시한다.

답을 추론해 나가는 과정도 아래 서술하겠지만, 사실 이런 서술을 무시하고도 Tuple을 Union으로 변환하는 게 저게 전부임을,

직관적으로 깨닫는 사람도 분명 있을 거라 생각한다.

 

type TupleToUnion<T extends any[]> = T['length'] extends 0 ? never : T[number];
type TupleToUnion<T extends any[]> = T extends [] ? never : T[number];

논리를 따라가면, T는 any[]를 확장하며, T의 length가 0이면 never, 그렇지 않다면 T[number]인 타입이라고 할 수 있다.

그러면 T['length']인 정수 중 0을 제외한 나머지로 이루어진 타입이기 때문에 유니온이 될 것이다.

이것은 다시 두 번째 줄처럼 변경할 수 있다.

length가 0이라는 것은 빈 배열이라는 의미기 때문이다.

다음으로 얘기할 것은, 전자의 never 타입은 어차피 결코 나올 수 없는 경우의 수라는 점이다.

 

type TupleToUnion<T extends any[]> = T extends [] ? T[number] : T[number];
type TupleToUnion<T extends any[]> = T extends [] ? T[0] : T[number];

사실 T가 빈 배열인 [] 타입인 시점에서, T[0] 이든 T[1] 이든 무얼 넣어도 같다.

빈 배열에 인덱스를 넣고 가리켜 봐야 결국 never이기 때문이다.

여기서는 이 인덱스를 0으로 한정하여, 아래와 같이 변경할 것이다.

그러면 처음에 얘기했던 대로 T[number]는 0이 아닌 나머지 정수들을 의미하고, 전자는 T[0]이기 때문에 참, 거짓을 합치면,

 

type TupleToUnion<T extends any[]> = T[number];

이런 타입이 된다.

never 타입을 왜 마음대로 바꿀 수 있는지는 아래 글을 보면서 생각해보자.

 

 

 

Exclude은 왜 T extends U ? never : T 인가?

// Question : Exclude type을 정의하라 type question = any; TypeScript Utility type인 Exclude의 정의를 보면 T extends U ? never : T 라는 매우 생소한 표현이 등장한다. 아니, Exclude는 두번째 타입 파라미터로 받은 U를

kscodebase.tistory.com

 

 

반응형