"매 widening을 끄는 가장 강력한 단언". TypeScript 3.4에 등장한 as const는 literal type을 보존하면서 모든 property를 readonly로 만든다. 매 modern TS 코드의 type-safety 핵심 도구.
매 핵심
매 동작 방식
매 literal (string, number, boolean, array, object literal) 을 narrow type 으로 고정
매 type widening 방지 — "hello" 는 string 이 X, 매 "hello" literal type
매 array → readonly tuple 변환
매 object → 매 모든 property readonly + literal type
매 작동 범위
매 literal expression 에만 적용 가능
매 변수 / 함수 호출 결과에 매 X
매 컴파일 타임 only — 매 runtime 영향 X
매 응용
Discriminated union 의 tag 정의.
Const enum 의 modern 대체 (literal object).
Tuple type 의 명시적 생성 (router params, fixed-length array).
Configuration object 의 immutable 보장.
💻 패턴
1. Widening 방지
// 매 widening
constx="foo";// type: string (let), "foo" (const)
lety="foo";// type: string (always widened)
// 매 as const
constx2="foo"asconst;// type: "foo"
lety2="foo"asconst;// type: "foo" — 매 let 도 narrow
// 매 array
constarr1=[1,2,3];// number[]
constarr2=[1,2,3]asconst;// readonly [1, 2, 3]
2. Discriminated Union Tag
constACTIONS={INCREMENT:"INCREMENT",DECREMENT:"DECREMENT",RESET:"RESET",}asconst;typeAction=|{type:typeofACTIONS.INCREMENT;payload: number}|{type:typeofACTIONS.DECREMENT;payload: number}|{type:typeofACTIONS.RESET};// 매 ACTIONS.INCREMENT 의 type 은 "INCREMENT" — 매 string X
3. Const Enum 대체
// 매 옛 방식 — const enum (tree-shaking 문제, --isolatedModules 충돌)
constenumColor{Red="red",Blue="blue"}// 매 modern 방식 — as const
constColor={Red:"red",Blue:"blue",}asconst;typeColor=typeofColor[keyoftypeofColor];// "red" | "blue"
4. Readonly Tuple
functionuseState<T>(initial: T){letvalue=initial;return[value,(v: T)=>{value=v;}]asconst;}// 매 return type: readonly [T, (v: T) => void]
// 매 destructure 시 정확한 type
const[count,setCount]=useState(0);
constROLES=["admin","user","guest"]asconst;typeRole=typeofROLES[number];// "admin" | "user" | "guest"
constHTTP_METHODS=["GET","POST","PUT","DELETE"]asconst;typeHttpMethod=typeofHTTP_METHODS[number];// 매 사용
functionfetchData(method: HttpMethod,url: string){/* ... */}fetchData("GET","/api");// ✅
fetchData("PATCH","/api");// ❌ Argument of type '"PATCH"' is not assignable
7. Generic Function 의 Inference
functionpick<T,KextendskeyofT>(obj: T,keys: readonlyK[]):Pick<T,K>{constresult={}asPick<T,K>;for(constkeyofkeys)result[key]=obj[key];returnresult;}constuser={id: 1,name:"Alice",age: 30};constsubset=pick(user,["id","name"]asconst);// 매 as const 없으면: keys 는 string[] 으로 추론 → K = string → 매 fail
// 매 as const 있으면: keys 는 readonly ("id" | "name")[] → K = "id" | "name"
매 결정 기준
상황
Approach
Magic string / number set
as const 객체 + typeof[keyof typeof]
Discriminated union tag
as const 로 literal 보장
Tuple return
함수 끝에 as const
Config / constants
매 as const 로 deep readonly
Const enum 사용 중
매 as const 객체로 마이그레이션
Mutable shared state
as const X — 매 readonly 가 방해
기본값: 매 literal data 에는 항상 as const 를 시도. 매 widening 이 의도일 때만 제외.
Adjacent: Readonly · Type Narrowing · Type Inference
🤖 LLM 활용
언제: 매 fixed set of values (action types, route names, status codes), tuple return, config object 정의 시 사용.
언제 X: runtime mutation 필요 시, generic widening 이 의도일 때, 매 single primitive variable (이미 const 로 충분).
❌ 안티패턴
Function call 에 적용: fetch() as const — 매 literal 이 X 라 효과 없음.
Mutable interface 와 충돌: as const 객체를 mutable interface 에 assign — 매 readonly mismatch 에러.
과도한 nesting: 매 깊은 readonly 가 매 사용처에서 매 type 좁힘 — 매 trade-off 고려.
type 와 value 혼동: typeof OBJ vs OBJ — 매 type 추출엔 typeof.