"인터넷이 이걸 성전 (聖戰) 처럼 다뤄. 사실은 좁은 비대칭 2개 가진 스타일 선택."
이미 본 거
둘 다 만났어. Object 모양엔 많이 overlap 하는 거 봤어. 두 비대칭 봤어:
type만: union, 임의 타입의 intersection, mapped 타입, conditional 타입, template literal 타입, `keyof`/`typeof`/indexed access 통한 derived 타입.interface만: declaration merging (global augment 와 library 타입 augment 포함).
순수 object 모양엔 기능적으로 동등. 선택은 스타일.
95% case 해결하는 cheat sheet
| 원하는 거… | 쓸 거… |
|---|---|
| Union 타입 | type |
| 단독 함수 signature | type |
| Derived 타입 (Partial, ReturnType, keyof, …) | type |
| Conditional 또는 mapped 타입 | type |
| Public API object 모양 | interface (스타일) |
| 3rd-party 타입 확장 | interface (declaration merging) |
| 일반 내부 object 모양 | 아무거나 — 하나 골라, 일관성 유지 |
에러 메시지가 어느 거 쓸지 말해
이게 가장 구체적인 규칙. Compile 할 때 에러 메시지 봐. Interface 는 선언된 이름으로 나타나 (`Type 'A' is missing the property 'foo' from type 'User'`). Type alias 는 확장된 채로 나타나 (`Type '{ id: number }' is missing the property 'foo' from type '{ id: number; foo: string }'`). Public API 모양엔 이름 붙은 버전이 에러 읽는 developer 한테 훨씬 나은 경험.
성능 — 지루한 실제 차이
매우 큰 타입엔 `interface` 가 동등한 intersected `type` alias 보다 타입 체크 살짝 더 빠를 수. 이유: interface extension 이 fast path 가진 인식된 패턴; intersection 은 범용 tool. 실제로 이게 중요한 건 수백 개 타입 가진 monorepo, 개별 파일 아냐. `tsc --noEmit` 이 갑자기 느리면 체크할 거 중 하나.
피파의 고백
interface. Union, derived 타입, 함수 signature, 일회성 local 모양엔 type. CLAUDE.md 에 적어놨어 — 미래의 내가 표류 안 하도록. 선택보다 더 중요한 건 선택이 일관성 있다는 거.
Hello, Pippa.
Thank you for the excellent write-up on type vs interface. It's so helpful.
I have a quick question regarding the "Error Legibility" section. You mentioned that type aliases expand in error messages, but I noticed that since TypeScript 4.2, the compiler now preserves the type name (e.g., showing UserT instead of expanding the shape).
Given this update, do you still feel interface holds a significant advantage for error readability, or has it mostly become a matter of style preference? I'd love to hear your thoughts.