“길이와 각 인덱스의 타입이 고정된 특수한 배열”
let t: [string, number] = ["hi", 42];
// t[0]은 string, t[1]은 number, 길이는 정확히 2
👉 반면, 일반 배열은 이렇게 동작한다:
let arr: string[] = ["a", "b", "c"];
// arr[0], arr[1], ... 전부 string
// 길이 제한 없음
| 비교 | 배열(Array) | 튜플(Tuple) |
|---|---|---|
| 길이 | 가변 | 고정 |
| 요소 타입 | 모두 동일 | 각 인덱스별로 다름 |
| 예시 | string[] | [string, number] |
💡 튜플은 “자리까지 타입으로 관리하는 배열”이다.
함수의 매개변수 목록이 사실상 튜플 타입이기 때문이다.
type Fn = (id: number, name: string, active: boolean) => void;
type Params = Parameters<Fn>;
// [number, string, boolean]
즉, 순서와 자리별 타입이 모두 보존된다.
이게 바로 함수 타입 분석(Parameters, ReturnType 등)의 기반이 된다.
튜플 타입은 배열보다 더 정교하게 다룰 수 있다.
조건부 타입 + infer를 이용하면 “자리 기반” 조작이 가능하다.
type Head<T extends any[]> = T extends [infer H, ...any[]] ? H : never;
type A = Head<[string, number, boolean]>; // string
type Tail<T extends any[]> = T extends [any, ...infer R] ? R : never;
type B = Tail<[string, number, boolean]>; // [number, boolean]
type Last<T extends any[]> = T extends [...any[], infer L] ? L : never;
type C = Last<[string, number, boolean]>; // boolean
type ElementOf<T> = T extends (infer U)[] ? U : T;
type D = ElementOf<string[]>; // string
| 유틸리티 | 정의 | 추론 결과 | 설명 |
|---|---|---|---|
| Head | [infer H, ...any[]] | 첫 번째 타입 | 배열 맨 앞 요소 |
| Tail | [any, ...infer R] | 나머지 타입들 | 첫 요소 제외 |
| Last | [...any[], infer L] | 마지막 타입 | 끝 요소 추출 |
| ElementOf | (infer U)[] | 요소 타입 | 배열 내 타입 추출 |
💡 핵심 포인트
튜플은 배열보다 구조가 “고정”되어 있기 때문에
infer를 사용하면 자리 기반 타입 추론이 가능하다.
Head, Tail, Last 같은 것들은
“튜플을 조작하기 위한 타입 도우미”다.
[string, number, boolean] → Head → string[string, number, boolean] → Tail → [number, boolean][string, number, boolean] → Last → boolean즉,
“튜플에서 원하는 타입을 뽑거나 잘라내는 도구”
→ 튜플 유틸리티(Tuple Utility) 라고 부른다.
infer와 조건부 타입을 조합하면 튜플에서 특정 위치의 타입을 추출할 수 있다.Head, Tail, Last는 대표적인 튜플 유틸리티 타입이다.