홈으로 돌아가기

TypeScript에서 HKT: 에뮬레이션과 실습

이 글은 Kind-mappings와 라이브러리를 통한 TypeScript에서 고차 종류 타입 에뮬레이션을 다룹니다. 아リティ 제한, 컨테이너를 위한 map 구현, 네이티브 지원 장벽을 설명합니다. 타입 안전한 FP 추상화 생성에 유용합니다.

TypeScript에서 HKT 에뮬레이션: Kind와 라이브러리
Advertisement 728x90

TypeScript에서 고차형 타입을 모방하는 실용적인 방법

TypeScript는 고차형 타입(HKT)을 기본적으로 지원하지 않아, Array, Set, Promise와 같은 타입 생성자 위에서 재사용 가능한 추상화를 만들 수 있는 데 제한이 있습니다. 고차형 타입은 요소 타입뿐만 아니라 컨테이너 자체까지 매개변수화할 수 있게 해주며, 함수형 패턴인 포인터(functor)와 모나드(monad)의 강력한 타입 안정성을 제공합니다. 이 기능이 없으면 각 데이터 타입마다 map과 같은 연산을 반복 구현해야 합니다.

예를 들어, Set에 대해 map을 구현하는 작업을 생각해 봅시다.

type MapSet = <A, B>(f: (a: A) => B, set: Set<A>) => Set<B>;

비슷하게 ReadonlySet, LinkedList, ReadonlyArray에도 각각 별도의 버전이 필요합니다. 고차형 타입이 없다면 중복 코드를 피할 수 없습니다. 하지만 HKT가 있다면 단순히 Mappable<F> 인터페이스로 F<A> → F<B> 형태의 시그니처를 정의할 수 있습니다.

Google AdInline article slot

TypeScript는 Type ‘F’ is not generic라는 오류를 발생시키는데, 이는 타입 종류(: 문자열)와 → *: 배열처럼 타입 생성자의 차이를 구분하지 못하기 때문입니다.

생성자 사전을 통한 모방

가장 간단한 대안은 문자열 키를 타입으로 매핑하는 사전 방식입니다.

interface TypeConstructors<A> {
  'Array': Array<A>;
  'LinkedList': LinkedList<A>;
  'ReadonlySet': ReadonlySet<A>;
  'Set': Set<A>;
}

type Kind<F extends keyof TypeConstructors<unknown>, A> = TypeConstructors<A>[F];

Kind<'Array', number>Array<number>로 확장됩니다. 이 기반 위에서 일반화된 타입을 구성할 수 있습니다:

Google AdInline article slot
type Mappable<F extends keyof TypeConstructors<unknown>> = <A, B>(
  f: (a: A) => B,
  list: Kind<F, A>
) => Kind<F, B>;

구체적인 타입에 대한 구현 예시:

const mapArray: Mappable<'Array'> = (f, list) => list.map(f);
const mapSet: Mappable<'Set'> = (f, list) => new Set(Array.from(list, f));

아리티 제한과 해결책

이 접근법은 단항 생성자()에는 잘 작동하지만, 이항 생성자인 Map<K, V>처럼 다중 매개변수를 받는 경우 별도의 사전이 필요합니다.

interface TypeConstructors2<A, B> {
  Map: Map<A, B>;
  Record: Record<A, B>;
}

type Kind2<F extends keyof TypeConstructors2<unknown, unknown>, A, B> = TypeConstructors2<A, B>[F];

다양한 아리티를 처리하는 것은 복잡해지며, 실제 프로젝트에서는 다음과 같은 라이브러리를 활용합니다:

Google AdInline article slot
  • hkt-toolbelt: 최대 4개의 매개변수를 지원하며, 포인터와 모나드를 위한 유틸리티 포함.
  • hkt-core: 타입 성능에 집중하고, 최소한의 API 표면적을 제공.

이 도구들은 실제 고차형 타입에 가까운 타입 추론을 제공하여 수동으로 사전을 관리할 필요 없게 만듭니다.

고차형 타입 채택의 주요 과제

2026년 기준으로도 고차형 타입은 여전히 추가되지 않았으며, 지속적인 요청(이슈 #1213, #55280)에도 불구하고 주요 장벽은 다음과 같습니다:

  • 컴파일러 복잡성: 종류 다형성(kind polymorphism) 도입, 타입 추론 확장, 구조적 타이핑 적응.
  • 성능 문제: 대규모 함수형 프로젝트에서 컴파일 시간 증가.
  • 설계적 트레이드오프: 표현력과 자바스크립트 호환성 간 균형, 문법 부담 회피.

제안된 해결책:

  • 타입 생성자를 위한 특수 마커(F<~>).
  • 새로운 문법 없이 조건부 타입 개선.
  • 기존 TypeScript 기능을 활용한 실용적인 모방.

가장 중요한 점

  • 고차형 타입은 종류 매핑을 통해 컨테이너의 엄격한 타입 보존이 가능합니다.
  • hkt-toolbelthkt-core와 같은 라이브러리는 중급 이상 프로젝트에서 통합을 간편하게 만듭니다.
  • 아리티는 별도의 사전이 필요하며, 단항 타입은 기초 사용 사례에 이상적입니다.
  • 미래의 네이티브 지원은 성능을 희생하지 않는 점진적 개선을 통해 가능할 수 있습니다.
  • 모방을 통해 Array, Set, Promise 등 다양한 타입에서 map, flatMap 등의 함수를 중복 없이 깔끔하게 구현할 수 있습니다.

— Editorial Team

Advertisement 728x90

다음 읽기