반응형
Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 |
Tags
- junit5
- ArrayList
- html
- math
- CSS
- vscode
- 정규식
- Eclipse
- Visual Studio Code
- HashMap
- 자바
- string
- 인텔리제이
- 테스트자동화
- java테스트
- IntelliJ
- 자바문법
- Array
- js
- 자바스크립트
- list
- javascript
- SpringBoot
- 단위테스트
- 배열
- 문자열
- 스프링부트
- junit
- input
- Java
Archives
- Today
- Total
어제 오늘 내일
[TypeScript] 6. 유니온과 인터섹션, 그리고 리터럴 타입 본문
이 글의 목표: TypeScript 타입 시스템의 뼈대인 "합집합(union)"과 "교집합(intersection)"을 이해하고, 실전 패턴을 익힙니다.
유니온(|): "이것 또는 저것"
여러 타입 중 하나일 수 있음을 나타냅니다.
// id는 문자열이거나 숫자일 수 있다
type ID = string | number;
let userId: ID = 100;
userId = "abc-123"; // 둘 다 허용
유니온의 값을 쓸 때는, 모든 타입에 공통으로 존재하는 것만 바로 접근할 수 있습니다.
function printId(id: string | number) {
// id.toUpperCase(); // ❌ number에는 toUpperCase가 없다
console.log(id.toString()); // ✅ string, number 모두 toString이 있다
// 각각 다르게 처리하려면 타입을 좁혀야 한다 (7편에서 자세히)
if (typeof id === "string") {
console.log(id.toUpperCase()); // 여기선 string 확정
} else {
console.log(id.toFixed(0)); // 여기선 number 확정
}
}
리터럴 유니온: 가장 실용적인 패턴
특정 값들만 허용하는 유니온은 실무에서 정말 자주 씁니다. enum 대신 즐겨 쓰이죠.
// 버튼의 크기를 세 가지로 제한
type ButtonSize = "small" | "medium" | "large";
function Button(size: ButtonSize) { /* ... */ }
Button("medium"); // ✅
// Button("huge"); // ❌ 허용되지 않은 값 → 오타·잘못된 값 방지
숫자 리터럴도 됩니다.
type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;
let roll: DiceRoll = 4;
// roll = 7; // ❌
인터섹션(&): "이것 그리고 저것"
여러 타입을 모두 만족해야 함을 나타냅니다. 즉, 속성들을 합칩니다.
type HasName = { name: string };
type HasAge = { age: number };
// 두 타입을 모두 만족 → name과 age를 둘 다 가져야 한다
type Person = HasName & HasAge;
const p: Person = { name: "철수", age: 30 }; // 둘 다 있어야 함
// const p2: Person = { name: "영희" }; // ❌ age 누락
인터섹션은 여러 작은 타입을 조합해 큰 타입을 만들 때 유용합니다.
type Timestamps = { createdAt: Date; updatedAt: Date };
type Identifiable = { id: string };
// 공통 속성을 재사용해 여러 엔티티를 조립한다
type Article = Identifiable & Timestamps & {
title: string;
body: string;
};
판별 유니온(Discriminated Union): 실전의 꽃
서로 다른 형태의 객체들을 하나의 유니온으로 묶되, 공통의 "태그" 속성으로 구분하는 패턴입니다. 상태 관리, API 응답 처리에 강력합니다.
// 각 타입은 kind라는 공통 태그를 가진다 (값은 서로 다름)
type Circle = { kind: "circle"; radius: number };
type Rectangle = { kind: "rectangle"; width: number; height: number };
type Triangle = { kind: "triangle"; base: number; height: number };
type Shape = Circle | Rectangle | Triangle;
function getArea(shape: Shape): number {
// kind를 확인하면 TypeScript가 나머지 속성을 자동으로 좁혀준다
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2; // 여기선 radius 접근 가능
case "rectangle":
return shape.width * shape.height; // 여기선 width, height 접근 가능
case "triangle":
return (shape.base * shape.height) / 2;
}
}
kind 값을 확인하는 것만으로 TypeScript가 해당 분기 안에서 정확한 타입을 알려줍니다. 잘못된 속성에 접근하면 즉시 에러가 납니다.
실전 예제: API 응답 상태
로딩·성공·실패 상태를 판별 유니온으로 표현하면 아주 깔끔합니다.
type ApiState<T> =
| { status: "loading" }
| { status: "success"; data: T }
| { status: "error"; message: string };
function render(state: ApiState<string[]>) {
switch (state.status) {
case "loading":
return "불러오는 중...";
case "success":
// 여기서만 data에 접근 가능 → data 없이 접근하는 실수를 막는다
return `${state.data.length}개 로드됨`;
case "error":
// 여기서만 message에 접근 가능
return `에러: ${state.message}`;
}
}
loading 상태에서 실수로 state.data에 접근하려 하면 컴파일러가 막아줍니다. 이것이 판별 유니온이 안전한 이유입니다.
정리
- 유니온(
|) 은 "여러 타입 중 하나". 리터럴 유니온으로 값을 제한하는 패턴이 특히 유용하다. - 인터섹션(
&) 은 "여러 타입을 모두 만족". 작은 타입을 조합해 큰 타입을 만든다. - 판별 유니온은 공통 태그로 구분되는 유니온으로, 상태·응답 처리에서 안전하고 강력하다.
다음 글에서는 유니온을 실제로 다루는 핵심 기술, "타입 좁히기"를 집중적으로 파고듭니다.
반응형
'IT > TypeScript' 카테고리의 다른 글
| [TypeScript] 8. 함수와 타입 — 오버로드, 선택적 매개변수, this (0) | 2026.08.10 |
|---|---|
| [TypeScript] 7. 타입 좁히기(Narrowing) (0) | 2026.08.10 |
| [TypeScript] 5. interface vs type — 무엇을 언제 쓸까 (0) | 2026.08.09 |
| [TypeScript] 4. 타입 추론 — 언제 타입을 직접 쓰고 언제 맡길 것인가 (0) | 2026.08.09 |
| [TypeScript] 3. 기본 타입 총정리 (0) | 2026.08.09 |
Comments