타입스크립트 기교
- 7.1 never 타입 이해하기
- 7.2 객체를 순회하는 방법 알기
- 7.3 Record 타입으로 키-값 관계 모델링하기
- 7.4 가변 인수 함수의 타입 안전하게 모델링하기
- 7.5 선택적 never로 불가능한 조합 차단하기
- 7.6 상표 붙이기로 명목적 타이핑 흉내내기
이전 장들에서 배운 도구를 실제로 조합해서 쓰는 응용편이야. 실전에서 자주 마주치는 까다로운 타입 문제들과 그 해결법을 모아놨거든.
2장에서 never가 공집합이라고 했는데, 실전에서 이걸 어떻게 쓰냐가 중요해. 가장 유용한 패턴이 **완전성 체크(exhaustiveness check)**야. switch문의 default에 assertNever(shape)를 넣으면, Shape에 새 멤버를 추가했는데 처리를 안 하면 컴파일 에러가 나. 빠뜨린 케이스를 컴파일 타임에 잡아주는 거지. 조건부 타입에서 필터링할 때도 never가 핵심이야 — null이나 undefined를 never로 바꿔서 유니온에서 제거하는 패턴이 NonNullable의 구현이거든.
객체를 for...in이나 Object.keys로 순회할 때 타입 에러가 나는 건 TS 쓰면서 누구나 한 번은 겪어. k가 keyof ABC가 아니라 string인 이유는 구조적 타이핑 때문이야. ABC를 만족하면서 추가 속성이 있는 객체가 들어올 수 있으니까, 키가 a | b | c만이라고 보장할 수 없거든. Object.entries를 쓰거나, keyof와 타입 단언을 활용하는 방법이 있어.
**Record<K, V>**는 키 타입의 모든 멤버에 대해 값 타입을 가지는 객체 타입을 만들어. 인덱스 시그니처보다 키를 더 구체적으로 지정할 수 있고, 리터럴 유니온을 키로 쓰면 모든 키가 필수가 돼서 하나 빠뜨리면 에러가 나지.
TS 4.0에서 도입된 **가변 튜플 타입(variadic tuple types)**을 쓰면 가변 인수 함수도 타입 안전하게 만들 수 있어. concat([1, 2], ['a', 'b'])의 결과가 [number, number, string, string]으로 정확히 추론되는 거야. 이벤트 이미터, curry/bind 함수, 파이프라인 함수 같은 곳에서 실전적으로 쓰여.
**선택적 never**는 불가능한 조합을 차단하는 기법이야. b?: never는 "b가 있으면 그 값은 never여야 한다"는 뜻인데, never에 대입할 수 있는 값은 없으니까 사실상 b를 쓸 수 없다는 의미가 돼. 상호 배타적인 속성을 표현할 때 유용하지.
마지막으로 상표 붙이기(branding). 구조적 타이핑에서는 USD와 EUR가 둘 다 number면 구분을 못 하잖아. number & { __brand: 'USD' } 같은 팬텀 타입을 만들면, 런타임 오버헤드 없이 타입 수준에서 구분할 수 있어. 단위가 다른 숫자(픽셀, 미터, 초), ID 타입(UserId와 PostId), 경로 타입(절대 경로와 상대 경로), 검증된 데이터(이메일 형식 통과 여부) 같은 데에 실전적으로 쓸 수 있지.
정리
7장 읽고 기억할 거 세 가지:
never는 완전성 체크와 불가능한 조합 차단에 핵심 도구다. switch의 default에assertNever를 넣는 패턴은 실전에서 매우 유용.- 객체 순회에서 타입 에러가 나면 구조적 타이핑을 떠올려라.
Object.keys의 반환 타입이string[]인 이유가 있다. - 상표 붙이기(branding)로 구조적 타이핑의 한계를 보완할 수 있다. 런타임 오버헤드 없이 의미적으로 다른 타입을 구분.