---
id: wiki-2026-0508-type-casting
title: Type Casting
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [타입 캐스팅, Type Assertion, as 단언]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [typescript, types, casting, assertion]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
  language: typescript
  framework: typescript-5.6
---

# Type Casting

## 매 한 줄
> **"매 TypeScript 의 'casting' 은 runtime conversion 아님 — 매 compile-time assertion"**. 매 `as` 는 매 'I know more than you, compiler'. 2026 TS 5.6 — `satisfies` + branded types 가 매 unsafe `as` 의 대부분 대체.

## 매 핵심

### 매 종류
- **Type Assertion** (`as T`): compile-time only — runtime no-op.
- **Type Casting** (other languages): runtime conversion.
- **`satisfies T`**: 매 assertion 없이 type check.
- **Type Guard**: runtime check + type narrow.

### 매 종류 비교
- 매 `value as T` — 매 unsafe (TS 가 검증 안함).
- 매 `value satisfies T` — 매 safe (TS 가 검증, 매 narrowing 보존).
- 매 `value as unknown as T` — 매 double assertion (마지막 escape).
- 매 `<T>value` — 매 old syntax, JSX 와 conflict.

### 매 응용
1. 매 JSON parse → typed.
2. 매 narrowed type 의 explicit signal.
3. 매 const assertion (`as const`) — literal type.

## 💻 패턴

### Type assertion
```typescript
const el = document.getElementById('app') as HTMLDivElement;
// 매 unsafe — element 가 div 가 아니면 runtime error 가능
```

### Safer: type guard
```typescript
const el = document.getElementById('app');
if (el instanceof HTMLDivElement) {
  el.innerText = 'hi'; // 매 narrowed safely
}
```

### `satisfies` (preferred)
```typescript
type Color = 'red' | 'green' | 'blue';
type Palette = Record<Color, string>;

// 매 satisfies — type check + literal preserve
const palette = {
  red: '#ff0000',
  green: '#00ff00',
  blue: '#0000ff',
} satisfies Palette;

palette.red.toUpperCase(); // ✅ string method 사용 가능

// 매 vs as — narrowing 잃음
const palette2 = {
  red: '#ff0000',
  green: '#00ff00',
  blue: '#0000ff',
} as Palette;
// palette2.red 는 string 으로 widen 됨 — 매 literal 잃음
```

### `as const`
```typescript
const config = {
  api: 'https://api.example.com',
  retries: 3,
  methods: ['GET', 'POST'],
} as const;
// 매 deeply readonly + literal types
// type: { readonly api: 'https://...', readonly retries: 3, readonly methods: readonly ['GET', 'POST'] }
```

### JSON parse with validation (zod)
```typescript
import { z } from 'zod';

const UserSchema = z.object({
  id: z.string(),
  name: z.string(),
  age: z.number().int().min(0),
});
type User = z.infer<typeof UserSchema>;

function parseUser(raw: unknown): User {
  return UserSchema.parse(raw); // 매 runtime validation + type
  // 매 NOT: return raw as User — unsafe
}
```

### Branded types (nominal)
```typescript
type UserId = string & { readonly __brand: 'UserId' };
type OrderId = string & { readonly __brand: 'OrderId' };

function toUserId(s: string): UserId { return s as UserId; }
function toOrderId(s: string): OrderId { return s as OrderId; }

const u: UserId = toUserId('u_1');
const o: OrderId = toOrderId('o_1');

function getUser(id: UserId) { /* ... */ }
getUser(u); // ✅
// getUser(o); // ❌ — branded mismatch
// getUser('u_1'); // ❌ — bare string
```

### Double assertion (last resort)
```typescript
const fromAny = (someJsValue as unknown) as MyType;
// 매 use only when 매 truly necessary — 매 escape hatch
```

### `unknown` over `any`
```typescript
// ❌ any — type system bypass
function bad(x: any) { x.foo.bar; } // 매 no error

// ✅ unknown — must narrow
function good(x: unknown) {
  if (typeof x === 'object' && x !== null && 'foo' in x) {
    // 매 narrowed
  }
}
```

### Discriminated union narrowing
```typescript
type Shape =
  | { kind: 'circle'; r: number }
  | { kind: 'square'; s: number };

function area(shape: Shape): number {
  switch (shape.kind) {
    case 'circle': return Math.PI * shape.r ** 2; // 매 narrowed
    case 'square': return shape.s ** 2;
  }
}
// 매 NO assertion needed — 매 narrowing 자동
```

## 매 결정 기준
| 상황 | Approach |
|---|---|
| 매 external data | zod / valibot — runtime validation |
| 매 config object literal | `satisfies` |
| 매 immutable config | `as const` |
| 매 nominal distinction | branded types |
| 매 DOM element | `instanceof` guard |
| 매 truly impossible to express | `as unknown as T` (last resort) |

**기본값**: 매 `as` 의 회피. 매 satisfies / guard / schema 의 사용.

## 🔗 Graph
- 부모: [[TypeScript]]
- 변형: [[Type_Assertion]] · [[Type_Guard]] · [[Branded_Types]]
- 응용: [[Zod]]
- Adjacent: [[Discriminated_Union]]

## 🤖 LLM 활용
**언제**: 매 `as` 의 alternative 제안, 매 zod schema 생성, 매 brand pattern.
**언제 X**: 매 actual runtime conversion 필요 — 매 TS casting 은 no-op.

## ❌ 안티패턴
- **`as any`**: 매 type system 의 포기.
- **`as` to silence error**: 매 root cause 미해결.
- **`as T` for parsed JSON**: 매 unvalidated trust.
- **Old `<T>` syntax in TSX**: 매 conflict — 매 `as` 사용.

## 🧪 검증 / 중복
- Verified (TS 5.6 handbook, satisfies operator RFC, zod docs, 2026).
- 신뢰도 A.

## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — TS type casting with satisfies, branded types, zod |
