---
id: wiki-2026-0508-readonly-type
title: Readonly Type
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [TypeScript Readonly, ReadonlyArray, Readonly Utility Type]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [typescript, readonly, immutability, type-system]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
  language: TypeScript
  framework: TS 5.7+
---

# Readonly Type

## 매 한 줄
> **"매 TypeScript 의 compile-time immutability"**. 매 `readonly` modifier (property level) + `Readonly<T>` utility type (object) + `ReadonlyArray<T>` (array) + `as const` (literal). 매 runtime 강제 X — 매 dev-time discipline. 2026 TS 5.7+ 매 `satisfies` / `const` type parameter 와 조합으로 강력.

## 매 핵심

### 매 4가지 형태
- **`readonly` property**: `interface User { readonly id: number; }` — 단일 property.
- **`Readonly<T>`**: 매 mapped type, 매 모든 property readonly.
- **`ReadonlyArray<T>` / `readonly T[]`**: 매 array, push/pop 등 mutation method 제거.
- **`as const`**: 매 literal value, deeply readonly + literal type 보존.

### 매 한계
- **Compile-time only**: 매 runtime mutation 가능 (cast, JS interop).
- **Shallow**: 매 `Readonly<T>` 매 nested object 는 mutable.
- **Type erasure**: 매 컴파일 후 일반 JS object — `Object.freeze()` 와 무관.

### 매 응용
1. Function parameter: 매 mutation 의 의도 차단.
2. State: 매 Redux store, React state — 매 immutable update 강제.
3. Configuration: 매 `as const` 로 literal type 보존.
4. API response type: 매 response 의 mutation 차단.

## 💻 패턴

### `readonly` property
```ts
interface User {
  readonly id: number;
  name: string;
}

const u: User = { id: 1, name: 'Alice' };
u.name = 'Bob'; // OK
u.id = 2;       // Error: Cannot assign to 'id' because it is a read-only property
```

### `Readonly<T>` utility
```ts
interface Config {
  apiUrl: string;
  timeout: number;
}

const config: Readonly<Config> = { apiUrl: '/api', timeout: 5000 };
config.apiUrl = '/v2'; // Error
```

### `ReadonlyArray<T>` / `readonly T[]`
```ts
function sum(nums: readonly number[]): number {
  // nums.push(0); // Error
  return nums.reduce((a, b) => a + b, 0);
}

const arr: readonly number[] = [1, 2, 3];
arr[0] = 99; // Error
```

### `as const` (deeply readonly literal)
```ts
const ROUTES = {
  HOME: '/',
  USERS: '/users',
  POSTS: '/posts',
} as const;

type Route = typeof ROUTES[keyof typeof ROUTES]; // '/' | '/users' | '/posts'

const TUPLE = [1, 'two', true] as const;
// type: readonly [1, 'two', true] (not (number | string | boolean)[])
```

### Deep Readonly (recursive)
```ts
type DeepReadonly<T> = {
  readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};

interface State {
  user: { name: string; settings: { theme: string } };
}
const s: DeepReadonly<State> = { user: { name: 'A', settings: { theme: 'dark' } } };
s.user.settings.theme = 'light'; // Error
```

### `satisfies` + `as const` (TS 5.7)
```ts
const config = {
  port: 3000,
  host: 'localhost',
} as const satisfies { port: number; host: string };

// config.port type: 3000 (literal), still validated
```

### Function `const` type parameter (TS 5.0+)
```ts
function tuple<const T extends readonly unknown[]>(arr: T): T {
  return arr;
}

const t = tuple(['a', 'b', 'c']); // type: readonly ['a', 'b', 'c']
```

### Branded readonly (runtime + type)
```ts
function freeze<T>(obj: T): Readonly<T> {
  return Object.freeze(obj) as Readonly<T>;
}

const config = freeze({ apiUrl: '/api' });
// config.apiUrl = '/v2'; // TS error + runtime error
```

## 매 결정 기준
| 상황 | Approach |
|---|---|
| Single property immutable | `readonly` modifier |
| Whole object immutable (shallow) | `Readonly<T>` |
| Array param (no mutation) | `readonly T[]` |
| Literal config | `as const` |
| Deeply nested state | `DeepReadonly<T>` 또는 Immer |
| Runtime guarantee 필요 | `Object.freeze()` + `Readonly<T>` |
| React state | useState (immutable update convention) |

**기본값**: 매 function parameter 매 `readonly T[]` 항상. 매 literal config 매 `as const`. 매 deep immutability 매 Immer.

## 🔗 Graph
- 부모: [[TypeScript]]
- 변형: [[const_assertion]]
- 응용: [[프론트엔드 및 UIUX 표준|Redux]]
- Adjacent: [[Satisfies Operator]]

## 🤖 LLM 활용
**언제**: API response type, function param (mutation 의도 차단), config object (`as const`), Redux state.
**언제 X**: 매 internal mutation-heavy class — readonly 의 noise.

## ❌ 안티패턴
- **`Readonly<T>` 의 deep 가정**: shallow 만 — `DeepReadonly<T>` 또는 Immer 사용.
- **Runtime immutability 가정**: TS readonly 매 compile-time only — JS cast 시 mutable.
- **`Readonly<T>` + class with method**: method 의 type 까지 readonly 처리 — 매 의도와 다른 동작 가능.
- **`as const` 남용 in mutable context**: 매 literal type 의 narrowness 가 unintended widening 차단.

## 🧪 검증 / 중복
- Verified (TypeScript 5.7 docs, TS handbook).
- 신뢰도 A.

## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — `as const` / `satisfies` / `const` type param 추가 |
