노트

유니언·인터섹션·리터럴 타입

Union, Intersection, and Literal Types

프런트엔드#ts · 연결된 개념 7개

쉽게 말하면

유니언은 'A이거나 B'인 값, 인터섹션은 'A이면서 B'인 값이에요. 고양이 반과 강아지 반을 합친 교실에선 모두에게 통하는 '이름 부르기'만 할 수 있듯, 유니언 값에선 공통 속성만 바로 쓸 수 있어요.

비유가 깨지는 곳 '합친다'는 말이 헷갈리기 쉬워요. 값의 집합으로는 유니언이 합집합이지만, 객체끼리 &는 속성이 합쳐지고 유니언끼리 &는 공통 멤버만 남아요. 같은 속성 타입이 충돌하면 never가 되기도 해요.

유니언 타입(Union Type, A | B)은 "A이거나 B인 값"이고, 인터섹션 타입(Intersection Type, A & B)은 "A이면서 B인 값"이다. 리터럴 타입(Literal Type)은 'left'나 3처럼 특정 값 하나만 허용하는 타입이다.

type Align = 'left' | 'right' | 'center'           // 리터럴 유니언
type Admin = { name: string; privileges: string[] }
type Employee = { name: string; startDate: Date }
type Elevated = Admin & Employee                   // 속성이 합쳐짐
  • 이름이 헷갈리는 이유: 유니언은 값의 집합에서 합집합이다. 그런데 "모자 쓴 키 큰 사람 방"과 "모자 쓴 스페인어 쓰는 사람 방"을 합치면, 모두에 대해 확실한 사실은 "모자를 썼다"뿐이다. 그래서 유니언 값에서는 공통 속성만 바로 쓸 수 있고, 나머지는 좁힌 뒤 쓴다
  • 객체끼리의 &는 속성이 합쳐지지만, 유니언끼리의 &는 공통 멤버만 남는다: (string | number) & (number | boolean)은 number
  • 같은 이름 속성의 타입이 충돌하는 객체를 &로 합치면 그 속성이 never가 되기 쉽다. 속성을 교체하려면 Omit으로 지운 뒤 합친다
  • 객체 전체를 리터럴 타입으로 고정하려면 as const를 쓴다
  • 리터럴 구분 필드를 가진 유니언은 판별 유니언이 되어 상태 모델링에 강력하다
  • interface의 extends와 &의 차이는 type과 interface

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 템플릿 리터럴 타입

    템플릿 리터럴 타입(Template Literal Types)은 문자열 리터럴 타입을 템플릿 문자열 문법으로 조합해 새 문자열 유니언을 만드는 기능이다. 유니언을 넣으면 가능한 모든 조합이 나온다.

  • 매핑된 타입과 keyof

    매핑된 타입(Mapped Types)은 기존 타입의 키를 하나씩 돌며 새 타입을 만드는 문법([K in keyof T]: …)이다. keyof T는 객체 타입의 키 유니언을, T[K](인덱스 접근 타입, Indexed Access Type)는 그 키의 값 타입을 꺼낸다.

  • enum과 as const 객체

    TypeScript의 enum은 관련된 상수 집합에 이름과 타입을 함께 주는 문법이다. 다른 TS 타입과 달리 런타임 객체로 컴파일되어 남는다. 요즘 프런트엔드에서는 같은 일을 as const 객체와 유니언 타입으로 하는 경우가 많다.

  • 타입 추론과 타입 검사

    타입 추론(Type Inference)은 표기가 없어도 컴파일러가 값의 타입을 정하는 단계이고, 타입 검사(Type Checking)는 정해진(추론됐거나 명시된) 타입을 코드가 지키는지 확인하는 단계다. 보통 추론이 먼저 일어나고, 그 결과를 기준으로 검사한다.

  • 설정 기반 UI

    화면 구조를 컴포넌트를 나열한 코드가 아니라 설정 데이터(보통 배열)로 선언하고, 렌더러가 그 설정을 읽어 그리는 패턴. 구조를 바꿀 때 렌더링 코드 대신 데이터만 고친다.

보기 옵션