"매 type 의 compatibility 의 name 이 아닌 shape 으로 결정". TypeScript / Go 의 핵심 — 매 nominal typing (Java / C#) 의 반대. 매 2026 TS 5.7 의 동일 원칙 — 매 modern web 의 fundamental.
매 핵심
매 Nominal vs Structural
Nominal (Java/C#): 매 declared name 의 일치 — 매 같은 shape 라도 다른 type 시 incompatible.
Structural (TS/Go): 매 properties / methods 의 shape 의 match 의 compatible — 매 declaration site 의 무관.
매 동작 원리
매 assignability check: 매 source type 의 모든 required member 의 target type 의 존재 의 확인.
매 method signature: 매 parameter 의 contravariant, return 의 covariant.
매 excess property checking: 매 object literal 의 special case — 매 추가 property 의 error.
매 응용
매 function parameter 의 minimal interface 의 require — 매 flexibility.
매 mock / stub 의 작성 의 자연스러움 — 매 test 의 친화.
매 ad-hoc type 의 inline definition.
💻 패턴
매 Structural 의 기본
interfacePoint{x: number;y: number;}classVector{constructor(publicx: number,publicy: number){}}functiondist(p: Point):number{returnMath.sqrt(p.x**2+p.y**2);}dist(newVector(3,4));// OK — 매 Vector 의 Point shape 의 satisfy
dist({x: 3,y: 4});// OK — 매 object literal 의 동일
매 Branded type 의 nominal 의 흉내
// 매 structural 의 약점 — 매 같은 shape 의 다른 의미 의 mix
typeUserId=string&{__brand:'UserId'};typeOrderId=string&{__brand:'OrderId'};functiongetUser(id: UserId){/* ... */}constoid='order-1'asOrderId;// getUser(oid); // 매 ERROR — 매 brand 의 mismatch
매 Function 의 contravariance
typeLogger=(msg: string)=>void;constwide:(msg: string|number)=>void=(m)=>console.log(m);constlog: Logger=wide;// OK — 매 parameter 의 contravariant
// 매 wide 의 string 도 number 도 받으므로 string-only 의 substitute 가능
매 Excess property checking 의 우회
interfaceConfig{url: string;}// declareConfig({ url: '/api', timeout: 5000 }); // ERROR — 매 excess
constcfg={url:'/api',timeout: 5000};declareConfig(cfg);// OK — 매 variable 의 우회 (매 fresh literal 만 check)
functiondeclareConfig(c: Config){/* ... */}
매 Subtyping 의 자동
interfaceAnimal{name: string;}interfaceDog{name: string;bark():void;}constdogs: Dog[]=[{name:'Rex',bark:()=>{}}];constanimals: Animal[]=dogs;// OK — 매 Dog 의 superset 의 자동 subtype
매 Class 의 structural 의 trap
classCat{meow() {}}classLion{meow() {}}constc: Cat=newLion();// OK?? — 매 동일 shape 의 compatible
// 매 nominal 기대 시 private field 의 brand 의 사용
classCatN{#species='cat';meow() {}}classLionN{#species='lion';meow() {}}// 매 #private 의 nominal effect — 매 cross-class 의 incompatible
매 Generic 의 structural 의 활용
functionpluck<T,KextendskeyofT>(arr: T[],key: K):T[K][]{returnarr.map(x=>x[key]);}// 매 T 의 shape 의 자유 — 매 keyof T 의 structural inference
constnames=pluck([{name:'a'},{name:'b'}],'name');
매 결정 기준
상황
Approach
일반 type
structural (default) — 매 TS 의 native
Domain ID 의 mix 방지
branded type
Strict nominal 필요
private field / unique symbol brand
External library compat
structural — 매 자연스러운 fit
기본값: structural typing 의 활용. 매 ID confusion 의 risk 시 branded type 의 추가.
🔗 Graph
부모: TypeScript · TypeScript 타입 시스템 (TypeScript Type System)
변형: Nominal-Typing-in-TypeScript · Duck Typing
응용: Excess_Property_Checking · ts-brand
Adjacent: Discriminated_Unions · Type Casting
🤖 LLM 활용
언제: TS type error 의 explain, branded type 의 권장, structural vs nominal 의 비교.
언제 X: Java/C# 같은 nominal 언어 의 답변 의 mix — 매 언어 의 명시.
❌ 안티패턴
ID confusion: 매 UserId / OrderId 의 같은 string — 매 brand 의 추가.
Class identity 의 의존: 매 instanceof 없이 type 만 의 distinguish — 매 trap.