---
id: typescript-const-assertions
title: TypeScript const Assertions
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [typescript, const, literal-types, vibe-coding]
tech_stack: { language: "TypeScript 5+", applicable_to: ["Web", "Backend"] }
applied_in: []
aliases: ["as const", literal narrowing, readonly tuple]
---

# const Assertions

> `as const` 는 "이 값을 가능한 가장 좁은 literal 타입으로". 배열 → readonly tuple, object → readonly + literal 필드. enum 대안으로 매우 유용.

## 📖 핵심 개념
기본 추론은 넓다 (`'red'` → `string`, `[1, 2]` → `number[]`). `as const` 추가하면 좁아진다 (`'red'` → `'red'`, `[1, 2]` → `readonly [1, 2]`).

## 💻 코드 패턴

### 1. enum 대체
```ts
const ROLES = ['admin', 'editor', 'viewer'] as const;
type Role = typeof ROLES[number]; // 'admin' | 'editor' | 'viewer'

function setRole(role: Role) { ... }
setRole('admin'); // ✅
setRole('xxx');   // ❌
```

### 2. config 객체
```ts
const CONFIG = {
  api: { baseUrl: 'https://api.example.com', timeout: 30 },
  features: { darkMode: true, beta: false },
} as const;

type Config = typeof CONFIG;
// 모든 필드 readonly + literal 타입
CONFIG.features.darkMode = false; // ❌ readonly
```

### 3. discriminated union 자동 생성
```ts
const ACTIONS = {
  add: (id: string) => ({ kind: 'add', id } as const),
  remove: (id: string) => ({ kind: 'remove', id } as const),
} as const;

type Action = ReturnType<typeof ACTIONS[keyof typeof ACTIONS]>;
// { kind: 'add'; id: string } | { kind: 'remove'; id: string }
```

### 4. tuple 보존
```ts
function pair<A, B>(a: A, b: B): [A, B] {
  return [a, b];
}
const p = pair(1, 'x'); // [number, string]

// vs
const arr = [1, 'x'];           // (string | number)[]
const tup = [1, 'x'] as const;  // readonly [1, 'x']
```

## 🤔 의사결정 기준
| 상황 | as const | enum | 그냥 string |
|---|---|---|---|
| 고정된 옵션 set + tree-shake 친화 | ✅ | ❌ (런타임 객체) | ❌ (literal 안 됨) |
| 자동 union 추출 (`typeof X[number]`) | ✅ | ❌ | ❌ |
| 숫자 enum 의 reverse mapping 필요 | ❌ | ✅ | ❌ |
| 라이브러리 export 호환성 (특히 esm/cjs 혼용) | ✅ | 까다로움 | — |
| 단일 사용 string | ❌ | ❌ | ✅ |

## ❌ 안티패턴
- **`as const` 후 mutation 시도**: readonly 위반. 새 객체 반환.
- **api response 에 `as const`**: runtime 값은 fixed 아님. literal 의미 없음. zod 스키마 + `.transform` 사용.
- **`as const` 와 `as Type` 혼용**: 의도 불명. 둘 중 하나로.
- **거대 객체 `as const`**: 추론 시간 증가. 큰 데이터는 schema validation + 일반 type.
- **enum 과 as const 혼용 한 코드베이스**: 일관성 깨짐. 한 컨벤션 선택.

## 🤖 LLM 활용 힌트
- 옵션 list / 상수 정의: "enum 대신 `as const` 배열 + `typeof X[number]`" 명시.
- 라이브러리 코드: enum 회피 (트리쉐이킹 / esm 호환성).

## 🔗 관련 문서
- [[TypeScript_Branded_Types]]
- [[Tagged_Union_Discriminated_Types]]
