--- id: wiki-2026-0508-as-const-assertion title: as const Assertion category: 10_Wiki/Topics status: verified canonical_id: self aliases: [const assertion, const context, readonly literal] duplicate_of: none source_trust_level: A confidence_score: 0.95 verification_status: applied tags: [typescript, type-system, literal-types, immutability] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: TypeScript framework: TypeScript 5.x --- # as const Assertion ## 매 한 줄 > **"매 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 ### 매 응용 1. Discriminated union 의 tag 정의. 2. Const enum 의 modern 대체 (literal object). 3. Tuple type 의 명시적 생성 (router params, fixed-length array). 4. Configuration object 의 immutable 보장. ## 💻 패턴 ### 1. Widening 방지 ```typescript // 매 widening const x = "foo"; // type: string (let), "foo" (const) let y = "foo"; // type: string (always widened) // 매 as const const x2 = "foo" as const; // type: "foo" let y2 = "foo" as const; // type: "foo" — 매 let 도 narrow // 매 array const arr1 = [1, 2, 3]; // number[] const arr2 = [1, 2, 3] as const; // readonly [1, 2, 3] ``` ### 2. Discriminated Union Tag ```typescript const ACTIONS = { INCREMENT: "INCREMENT", DECREMENT: "DECREMENT", RESET: "RESET", } as const; type Action = | { type: typeof ACTIONS.INCREMENT; payload: number } | { type: typeof ACTIONS.DECREMENT; payload: number } | { type: typeof ACTIONS.RESET }; // 매 ACTIONS.INCREMENT 의 type 은 "INCREMENT" — 매 string X ``` ### 3. Const Enum 대체 ```typescript // 매 옛 방식 — const enum (tree-shaking 문제, --isolatedModules 충돌) const enum Color { Red = "red", Blue = "blue" } // 매 modern 방식 — as const const Color = { Red: "red", Blue: "blue", } as const; type Color = typeof Color[keyof typeof Color]; // "red" | "blue" ``` ### 4. Readonly Tuple ```typescript function useState(initial: T) { let value = initial; return [value, (v: T) => { value = v; }] as const; } // 매 return type: readonly [T, (v: T) => void] // 매 destructure 시 정확한 type const [count, setCount] = useState(0); ``` ### 5. 매 Object 의 Deep Readonly ```typescript const config = { api: { baseUrl: "https://api.example.com", timeout: 5000, retries: 3, }, features: ["auth", "billing"], } as const; // type: // { // readonly api: { // readonly baseUrl: "https://api.example.com"; // readonly timeout: 5000; // readonly retries: 3; // }; // readonly features: readonly ["auth", "billing"]; // } // config.api.timeout = 1000; // ❌ readonly ``` ### 6. 매 Type Extraction ```typescript const ROLES = ["admin", "user", "guest"] as const; type Role = typeof ROLES[number]; // "admin" | "user" | "guest" const HTTP_METHODS = ["GET", "POST", "PUT", "DELETE"] as const; type HttpMethod = typeof HTTP_METHODS[number]; // 매 사용 function fetchData(method: HttpMethod, url: string) { /* ... */ } fetchData("GET", "/api"); // ✅ fetchData("PATCH", "/api"); // ❌ Argument of type '"PATCH"' is not assignable ``` ### 7. Generic Function 의 Inference ```typescript function pick(obj: T, keys: readonly K[]): Pick { const result = {} as Pick; for (const key of keys) result[key] = obj[key]; return result; } const user = { id: 1, name: "Alice", age: 30 }; const subset = pick(user, ["id", "name"] as const); // 매 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 이 의도일 때만 제외. ## 🔗 Graph - 부모: [[TypeScript]] - 변형: [[const Assertion]] · [[satisfies Operator]] - 응용: [[Discriminated_Unions|Discriminated Unions]] · [[Literal Types]] - Adjacent: [[Readonly]] · [[Type Narrowing]] ## 🤖 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`. ## 🧪 검증 / 중복 - Verified (TypeScript 3.4+ release notes, TS Handbook 2025 edition). - 신뢰도 A. - 매 [[Const Assertions]] 와 동의어 — 매 같은 기능. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — as const 의 7 패턴 + decision matrix |