유니온·리터럴 타입과 typeof·in·instanceof를 이용한 narrowing, 판별 유니온을 다룬다.
유니온과 타입 좁히기
하나의 값이 여러 타입 중 하나일 수 있을 때 유니온 타입을 씁니다. 그리고 그 값을 안전하게 다루려면 "지금 어떤 타입인지" 좁혀 가는 narrowing 이 필요합니다.
학습 목표
- 유니온 타입을 선언하고 사용한다.
typeof,in,instanceof로 타입을 좁힌다.- 판별 유니온(discriminated union)을 설계한다.
- 모든 경우를 처리했는지 검사한다.
유니온 타입
| 로 "이거 또는 저거"를 표현합니다.
let id: string | number;
id = 'abc'; // OK
id = 123; // OK
id = true; // ❌ string도 number도 아님
유니온 값은 공통으로 가능한 동작만 바로 쓸 수 있습니다.
function printId(id: string | number) {
console.log(id.toUpperCase()); // ❌ number엔 toUpperCase가 없음
}
그래서 타입을 좁혀야 합니다.
typeof 로 좁히기
원시 타입은 typeof 로 구분합니다. 조건문 안에서 TypeScript가 자동으로 타입을 좁혀 줍니다.
function printId(id: string | number) {
if (typeof id === 'string') {
console.log(id.toUpperCase()); // 여기선 id가 string
} else {
console.log(id.toFixed(2)); // 여기선 id가 number
}
}
in 으로 좁히기
객체에 특정 속성이 있는지로 구분할 때 in 을 씁니다.
type Bird = { fly: () => void };
type Fish = { swim: () => void };
function move(animal: Bird | Fish) {
if ('fly' in animal) {
animal.fly(); // Bird
} else {
animal.swim(); // Fish
}
}
instanceof 로 좁히기
클래스 인스턴스는 instanceof 로 구분합니다.
function format(value: Date | string) {
if (value instanceof Date) {
return value.toISOString(); // Date
}
return value.trim(); // string
}
| 방법 | 용도 |
|---|---|
typeof | 원시 타입(string/number/boolean...) |
in | 객체의 속성 존재 여부 |
instanceof | 클래스 인스턴스 |
판별 유니온
객체 유니온을 다루는 가장 강력한 패턴입니다. 각 타입에 공통 리터럴 필드(판별자) 를 두면, 그 값으로 안전하게 구분할 수 있습니다.
type Circle = { kind: 'circle'; radius: number };
type Square = { kind: 'square'; size: number };
type Shape = Circle | Square;
function area(shape: Shape): number {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2; // Circle로 좁혀짐
case 'square':
return shape.size ** 2; // Square로 좁혀짐
}
}
💡 TIP —
kind,type,tag같은 리터럴 필드를 판별자로 두는 것이 판별 유니온의 핵심입니다.switch와 궁합이 아주 좋습니다.
모든 경우 처리 확인
새 타입을 유니온에 추가했는데 처리를 빠뜨리면 위험합니다. never 를 이용하면 처리 안 된 경우를 컴파일 단계에서 잡을 수 있습니다.
function area(shape: Shape): number {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2;
case 'square':
return shape.size ** 2;
default:
const _exhaustive: never = shape; // 새 타입 추가 시 여기서 오류
return _exhaustive;
}
}
⚠️ 주의 — 나중에
Triangle같은 타입을Shape에 추가하면, 위default에서 즉시 타입 오류가 납니다. 이것이 처리 누락을 막아 주는 안전장치입니다.
요약
- 유니온
A | B는 여러 타입 중 하나임을 나타낸다. typeof/in/instanceof로 타입을 좁혀 안전하게 쓴다.- 공통 리터럴 필드를 둔 판별 유니온은
switch와 잘 맞는다. never로 모든 경우를 처리했는지 컴파일 단계에서 검사할 수 있다.
댓글 0
“TypeScript” 강좌에 대한 댓글입니다.