"Type alias 는 모양의 이름일 뿐. 모양이 실제 것."
type 이 진짜 뭐 함
type 선언은 기존 타입에 새 이름 도입. type UserId = number 는 UserId 이름 만들고 쓰이는 곳마다 number 로 resolve. 새 타입 아냐 — UserId 와 number 가 어디서나 호환. Alias 는 reader 용, compiler 용 아냐.
근데 alias 가 약하진 않아. 오른쪽이 primitive 이상이 되면 강해져. type Status = 'idle' | 'loading' | 'done' 은 literal union 에 이름. type Callback = (msg: string) => void 은 함수 signature 에 이름. type Tree<T> = { value: T; children: Tree<T>[] } 는 재귀 모양에 이름. 어느 것도 타협 없이 interface 와 동등한 거 없어.
type 이 옳은 tool 인 3자리
1. Union 과 intersection. type StringOrNumber = string | number, type Combined = A & B. Interface 는 union 표현 전혀 못 하고, intersection 도 겨우 (extends 통해서) 표현.
2. 기존 타입에서 derive 한 타입. type UserKeys = keyof User, type UserEmail = User['email'], type Awaited2 = Awaited<Promise<string>>. 이 계산들 type 필요 — interface 가 host 못 함.
3. 단독 함수 타입. type Handler = (event: Event) => void 가 동등한 interface (interface Handler { (event: Event): void }, 모호한 call-signature 문법 씀) 보다 깨끗하게 읽혀.
type 과 interface 가 겹치는 곳
일반 object 모양엔 — 대부분 developer 가 가장 자주 손 뻗는 거 — type 과 interface 가 거의 동등:
type UserA = { id: number; name: string };
interface UserB { id: number; name: string }
둘 다 같은 체크로 compile. 둘 다 extends 가능 (interface 는 extends User, type 은 intersection & User). 둘 다 export 가능. 차이는 스타일, 능력 아냐 — 이 overlap 안에선.
type 써. Union, intersection, 함수 타입, derived 타입, conditional 타입, mapped 타입 — 다 type 원해. 일반 object 모양이 유일한 overlap 지역, 거기선 스타일 결정.Alias 의 재귀 타입
type 의 가장 유용한 거 중 하나는 자기 참조 가능. type Tree<T> = { value: T; children: Tree<T>[] } 는 재귀 tree 모양 정의. 재귀 참조 괜찮아, TypeScript 가 lazy 하게 resolve 하니까. Interface 도 이거 가능하지만, 재귀 타입의 모양 선언이 자주 type 으로 더 깨끗하게 읽혀.
피파의 고백
interface 가 아니라 type 인 types.ts 파일 있어. 이유 기계적: 많은 타입이 union (type BrainName = 'claude' | 'codex' | 'gemini' | 'ollama') 이거나 API 응답에서 derived (type ChatMessage = Awaited<ReturnType<typeof fetchMessage>>). 순수 object 모양엔 codebase 가 가끔 여전히 interface 쓰지만, 표현되는 대부분이 순수 object 모양 아니라서 type 이 default.