개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

유니온과 교차 타입 — 타입을 조합하는 두 가지 방법

2025년 11월 13일
TypeScriptUnion TypeIntersection Type타입Narrowing

TypeScript에서 타입은 조합할 수 있습니다. | 연산자는 여러 타입 중 하나를 허용하고, & 연산자는 여러 타입의 특성을 모두 합칩니다. 이 두 연산자를 이해하면 복잡한 데이터 구조도 정확하게 표현할 수 있습니다.

유니온 타입 (|)

A | B는 A이거나 B인 타입입니다. 둘 중 하나면 됩니다.

type StringOrNumber = string | number;

function format(value: StringOrNumber): string {
  if (typeof value === "string") {
    return value.trim();
  }
  return value.toFixed(2);
}

format("  안녕  ");  // "안녕"
format(3.14159);    // "3.14"

유니온 타입의 값을 사용하기 전에는 실제 타입이 무엇인지 확인해야 합니다. TypeScript는 확인하지 않으면 공통 메서드만 허용합니다.

function print(value: string | number) {
  value.toString();  // 정상 — string과 number 모두 toString을 가짐
  value.toUpperCase();  // 오류 — number에는 toUpperCase가 없음
}

리터럴 유니온

특정 값만 허용하는 패턴입니다. 문자열 열거형처럼 쓸 수 있습니다.

type Direction = "left" | "right" | "up" | "down";
type StatusCode = 200 | 400 | 401 | 403 | 404 | 500;

function move(direction: Direction) {
  console.log(`${direction}으로 이동`);
}

move("left");   // 정상
move("back");   // 오류: '"back"'은 'Direction'에 할당할 수 없습니다

판별 유니온

객체 유니온에서 공통 프로퍼티로 타입을 구별하는 패턴입니다. TypeScript가 해당 분기에서 정확한 타입을 알 수 있어 안전하게 사용할 수 있습니다.

type Circle = {
  kind: "circle";
  radius: number;
};

type Rectangle = {
  kind: "rectangle";
  width: number;
  height: number;
};

type Shape = Circle | Rectangle;

function getArea(shape: Shape): number {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2; // 여기서 shape는 Circle로 확정
    case "rectangle":
      return shape.width * shape.height;  // 여기서 shape는 Rectangle로 확정
  }
}

교차 타입 (&)

A & B는 A이면서 동시에 B인 타입입니다. 두 타입의 모든 프로퍼티를 가져야 합니다.

type HasName = { name: string };
type HasAge = { age: number };

type Person = HasName & HasAge;

const person: Person = {
  name: "철수",
  age: 30,
  // 둘 다 있어야 함
};

타입 확장

교차 타입은 기존 타입에 프로퍼티를 추가하는 데 자주 쓰입니다.

type User = {
  id: number;
  name: string;
};

type UserWithTimestamp = User & {
  createdAt: Date;
  updatedAt: Date;
};

const user: UserWithTimestamp = {
  id: 1,
  name: "철수",
  createdAt: new Date(),
  updatedAt: new Date(),
};

함수 타입 교차

함수 타입을 교차하면 오버로드처럼 동작합니다.

type Stringify = (value: number) => string;
type Parse = (value: string) => number;

type Converter = Stringify & Parse;

유니온 vs 교차 타입

유니온 (A | B)교차 (A & B)
의미A이거나 BA이면서 B
요구 사항하나만 만족둘 다 만족
결과공통 멤버만 사용 가능모든 멤버 사용 가능
사용 목적다양한 입력 허용타입 합성 및 확장
type A = { a: string };
type B = { b: number };

type Union = A | B;
// { a: string } 또는 { b: number } — 공통 프로퍼티 없으면 아무것도 접근 불가

type Intersection = A & B;
// { a: string; b: number } — 둘 다 있어야 하고 둘 다 접근 가능

실전 활용 — API 응답 모델링

type ApiSuccess<T> = {
  status: "success";
  data: T;
};

type ApiError = {
  status: "error";
  message: string;
  code: number;
};

type ApiResponse<T> = ApiSuccess<T> | ApiError;

function handleResponse<T>(response: ApiResponse<T>) {
  if (response.status === "success") {
    console.log(response.data); // ApiSuccess<T>로 확정
  } else {
    console.error(response.message); // ApiError로 확정
  }
}

유니온 타입은 여러 가능성 중 하나를 표현하고, 교차 타입은 여러 타입의 특성을 하나로 합칩니다. 판별 유니온 패턴은 switch/if 분기에서 TypeScript가 정확한 타입을 추론할 수 있게 해주어, 실수 없이 각 케이스를 처리하는 데 큰 도움이 됩니다.

← 이전 글Interface — 객체의 형태를 정의하는 계약
다음 글 →타입 시스템 — TypeScript가 JavaScript에 더한 것