기본 패턴
type Named = { name: string };
type Aged = { age: number };
type Person = Named & Aged;
const user: Person = { name: "Mina", age: 26 };
// 여러 능력을 합치는 패턴
type Serializable = { toJSON(): string };
type Identifiable = { id: string };
type Entity = Serializable & Identifiable;설명
intersection은 "A이거나 B"가 아니라 "A이면서 동시에 B"를 요구한다
A & B는 union(A | B)과 반대 방향입니다. union이 A 또는 B 중 하나를 만족하면 되는 반면, intersection은 A와 B 양쪽의 조건을 모두 만족해야 합니다. 결과 타입은 두 타입의 모든 프로퍼티를 갖춰야 합니다.
type WithName = { name: string };
type WithRole = { role: "admin" | "user" };
type AdminUser = WithName & WithRole;
const admin: AdminUser = {
name: "Mina",
role: "admin",
};이 패턴은 여러 독립적인 타입 조각을 조합해 하나의 구체적인 타입을 만들 때 특히 유용합니다.
객체 타입 intersection은 프로퍼티를 병합하고, 원시 타입 intersection은 never가 된다
객체 타입끼리의 intersection은 두 타입의 프로퍼티가 합쳐진 결과를 만듭니다. 반면 string & number처럼 원시 타입끼리는 두 조건을 동시에 만족하는 값이 존재하지 않으므로 never가 됩니다.
type A = { x: number };
type B = { y: string };
type C = A & B; // { x: number; y: string }
type Impossible = string & number; // never같은 키가 두 타입에 서로 다른 타입으로 존재하면, 해당 키의 타입도 intersection이 됩니다.
type X = { id: string };
type Y = { id: number };
type Z = X & Y;
// Z.id의 타입은 string & number = never
// 어떤 값도 할당 불가능한 타입interface extends와 intersection은 비슷하지만 충돌 처리 시점이 다르다
interface C extends A, B와 type C = A & B는 대부분 같은 결과를 내지만, 충돌 키 처리 방식이 다릅니다.
interface Named { name: string }
interface Aged { age: number }
// interface 방식 — 충돌 시 선언 시점에 즉시 오류
interface Person extends Named, Aged {}
// intersection 방식 — 선언 시 오류 없음, 사용 시점에 드러남
type Person = Named & Aged;interface extends는 충돌하는 메서드 시그니처가 있을 때 선언 즉시 오류를 냅니다. intersection은 오류 없이 병합하지만 결과 타입이 never가 되어 사용 시점에야 문제가 드러납니다. 오류를 빨리 잡으려면 interface extends가 낫고, 조건부 타입이나 제네릭 조합처럼 유연한 타입 조작이 필요하면 intersection을 씁니다.
빠른 정리
| 상황 | 적합한 선택 |
|---|---|
| "A이거나 B" 표현 | union A | B |
| "A이면서 B" 동시 만족 | intersection A & B |
| 여러 타입 조각을 하나로 조합 | intersection |
| 충돌 키 오류를 선언 시점에 | interface extends |
| 제네릭·유틸리티 타입 조합 | intersection |
| 원시 타입끼리 intersection | never이 됨 — 의도한 경우만 |
주의할 점
같은 키가 양쪽 타입에서 다른 타입으로 선언되면 intersection 결과는 never가 됩니다. 해당 프로퍼티에 어떤 값도 할당할 수 없게 되어 실질적으로 사용 불가능한 타입이 만들어집니다.
type A = { id: string };
type B = { id: number };
type C = A & B;
// C.id의 타입: string & number = never
// ❌ 어떤 값도 할당 불가
const c1: C = { id: "x" }; // 오류
const c2: C = { id: 1 }; // 오류참고 링크
1 sources