0Pricing
TypeScript Academy · 강의

타입 수준 재귀

재귀 조건부 타입으로 타입을 순회합니다.

타입 수준 재귀은(는) CoddyKit의 무료 TypeScript Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 TypeScript Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. TypeScript Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

타입에서의 재귀

조건부 타입은 자기 자신을 참조할 수 있습니다. 이를 통해 타입 언어에 반복 기능이 생깁니다. 대부분의 타입 수준 재귀는 튜플을 한 요소씩 순회하면서 첫 요소를 떼어 내고 나머지에 재귀를 적용합니다.

type Length<T extends unknown[]> =
  T extends [unknown, ...infer Rest]
    ? Length<Rest>
    : 0;
// (this counts down to a base case)

기본 사례

모든 재귀에는 중지 조건이 필요합니다. 튜플에서는 보통 빈 튜플이 중지 조건입니다. [head, ...rest] 패턴이 더 이상 일치하지 않으면 끝에 도달한 것이므로 고정된 결과를 반환합니다.

type IsEmpty<T extends unknown[]> =
  T extends [] ? true : false;

type A = IsEmpty<[]>;     // true
type B = IsEmpty<[1, 2]>; // false

첫 요소와 나머지

핵심 동작은 전개 패턴과 함께 infer를 사용하여 튜플을 첫 번째 요소와 남은 튜플로 나누는 것입니다.

type Head<T extends unknown[]> = T extends [infer H, ...unknown[]] ? H : never;
type Tail<T extends unknown[]> = T extends [unknown, ...infer R] ? R : [];

type A = Head<[1, 2, 3]>; // 1
type B = Tail<[1, 2, 3]>; // [2, 3]

요소별로 처리하기

첫 요소, 나머지, 재귀를 결합하여 전체 튜플을 변환합니다. ToStrings는 각 요소 타입을 string으로 바꾸면서 튜플을 다시 만듭니다.

type ToStrings<T extends unknown[]> =
  T extends [infer H, ...infer R]
    ? [string, ...ToStrings<R>]
    : [];

type A = ToStrings<[1, true, 3]>; // [string, string, string]

누적기 패턴

결과를 누적기라는 추가 매개변수에 쌓아 올리는 경우가 많습니다. 누적기는 비어 있는 상태로 시작해 각 단계마다 커집니다. 이렇게 하면 구조를 다시 순회하지 않아도 되므로 타입 수준 반복에서 표준 기법으로 사용됩니다.

type Reverse<T extends unknown[], Acc extends unknown[] = []> =
  T extends [infer H, ...infer R]
    ? Reverse<R, [H, ...Acc]>
    : Acc;

type A = Reverse<[1, 2, 3]>; // [3, 2, 1]

누적기 따라가기

Reverse<[1,2,3]>를 추적해 보세요.

  • 1단계: H=1, Acc가 [1]이 됩니다
  • 2단계: H=2, Acc가 [2,1]이 됩니다
  • 3단계: H=3, Acc가 [3,2,1]이 됩니다
  • 튜플이 비었으므로 Acc = [3,2,1]을 반환합니다

누적기는 각 재귀 호출을 거치며 답을 전달합니다.

type R = Reverse<["a", "b"]>; // ["b", "a"]

유니언에 재귀 적용하기

문자열 유니언을 하나로 합치기 위해 재귀를 사용할 수도 있습니다. 여기서는 튜플 요소를 구분자로 연결하여 하나의 문자열 리터럴 타입으로 만듭니다.

표기법: 실제 TypeScript에서는 달러 중괄호 구멍이 포함된 문자열을 백틱으로 감싼 형태로 템플릿 리터럴 타입을 작성합니다. 이 예제에서는 각 부분을 순서대로 나열하여 해당 패턴을 Tpl<...>로 표시합니다. 예를 들어 리터럴 접두사와 그 뒤의 Rest에 일치하는 백틱 템플릿은 Tpl<'prefix', infer Rest>로 나타냅니다.

type Join<T extends string[], Sep extends string = ','> =
  T extends [infer H extends string, ...infer R extends string[]]
    ? R extends []
      ? H
      : Tpl<H, Sep, Join<R, Sep>>
    : '';
// Tpl<H, Sep, ...> builds a template literal type joining the parts

type A = Join<['a', 'b', 'c']>; // 'a,b,c'

재귀로 세기

재귀와 누적기를 함께 사용하면 셀 수 있습니다. 입력과 같은 길이가 되도록 unknown으로 이루어진 튜플을 만든 다음, 나중에 그 length를 읽습니다. 산술 과정에서 이 기법을 많이 사용하게 됩니다.

type Count<T extends unknown[], Acc extends unknown[] = []> =
  T extends [unknown, ...infer R]
    ? Count<R, [unknown, ...Acc]>
    : Acc["length"];

type A = Count<["x", "y", "z"]>; // 3

재귀로 필터링하기

튜플을 순회하면서 조건에 일치하는 요소만 남기고 나머지는 버립니다. 요소를 누적기에 추가하지 않으면 해당 요소를 건너뛸 수 있습니다.

type KeepStrings<T extends unknown[], Acc extends unknown[] = []> =
  T extends [infer H, ...infer R]
    ? H extends string
      ? KeepStrings<R, [...Acc, H]>
      : KeepStrings<R, Acc>
    : Acc;

type A = KeepStrings<[1, "a", 2, "b"]>; // ["a", "b"]

재귀 깊이 제한

컴파일러는 재귀 깊이를 제한합니다. 역사적으로 약 50 정도였으며, 꼬리 재귀 최적화를 사용하면 일부 패턴에서 더 깊어질 수 있습니다. 매우 큰 튜플에서는 Type instantiation is excessively deep 오류가 발생할 수 있습니다. 누적기를 사용하는 꼬리 재귀 방식으로 제한을 더 높일 수 있습니다.

type Repeat<T, N extends number, Acc extends T[] = []> =
  Acc["length"] extends N ? Acc : Repeat<T, N, [...Acc, T]>;

type A = Repeat<0, 3>; // [0, 0, 0]

모두 결합하기

첫 요소와 나머지로 나누기, 기본 사례, 누적기는 거의 모든 타입 수준 반복을 구성하는 세 가지 요소입니다. 이들을 사용하면 타입 시스템 안에서만 튜플을 매핑하고, 필터링하고, 뒤집고, 세고, 결합할 수 있습니다.

type MapToPairs<T extends unknown[], Acc extends unknown[] = []> =
  T extends [infer H, ...infer R]
    ? MapToPairs<R, [...Acc, [H, H]]>
    : Acc;

type A = MapToPairs<[1, 2]>; // [[1, 1], [2, 2]]

빠른 확인

누적기 패턴에 대한 이해도를 확인해 보세요.

복습

이제 타입 수준에서 반복문을 작성할 수 있습니다.

  • 자기 참조 조건부 타입이 재귀를 만듭니다.
  • 튜플을 [H, ...R]로 나누고 나머지에 재귀를 적용합니다.
  • 기본 사례인 빈 튜플이 반복을 멈춥니다.
  • 누적기가 결과를 만들고 깊은 재귀를 가능하게 합니다.

다음은 유니언에서 조건부 타입이 특별하게 동작하는 방식입니다.

자주 묻는 질문

“타입 수준 재귀” 강의는 무료인가요?

네 — “타입 수준 재귀” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 TypeScript Academy 강의 전체를 잠금 해제할 수 있습니다. TypeScript Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“타입 수준 재귀”에서 뭘 배우나요?

재귀 조건부 타입으로 타입을 순회합니다. 브라우저에서 직접 실행하는 실습 코드로 TypeScript Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

TypeScript Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 TypeScript Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“타입 수준 재귀” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 TypeScript Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 TypeScript Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 계산 언어로서의 타입
  2. 타입 수준 조건문
  3. 타입 수준 재귀
  4. 분배 조건부 타입
← TypeScript Academy(으)로 돌아가기