---
id: wiki-2026-0508-result-type
title: Result Type
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [Result, Either, Outcome]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [error-handling, types, functional]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
  language: TypeScript/Rust
  framework: neverthrow/Effect TS/std::result
---

# Result Type

## 매 한 줄
> **"매 error 를 value 로 만들어 type system 이 강제 handle 하게 함"**. Rust 의 `Result<T, E>`, Haskell `Either e a`, OCaml `result`, Swift `Result` 가 origin. TypeScript ecosystem 에서 매 neverthrow, Effect TS, ts-results 가 mainstream. 매 throw/catch 의 invisible control flow 와 unsafe error 의 alternative.

## 매 핵심

### 매 motivation
- Exception 은 type signature 에 안 보임 → 매 caller 가 forget 가능.
- `Result<T, E>` 는 매 return type 에 explicit → handle X 면 type error.
- 매 functional composition 에 friendly (map, andThen, mapErr).

### 매 ADT shape
- `Ok(T)` | `Err(E)` — 매 두 variant 의 sum type.
- `unwrap`, `unwrap_or`, `map`, `andThen` (flatMap), `match`.

### 매 응용
1. Validation pipeline (parse → transform → save).
2. Network call wrapping (fetch, DB query).
3. Domain error modeling (NotFound, Unauthorized, Conflict).
4. Recoverable failure (vs panic / unrecoverable).

## 💻 패턴

### TypeScript discriminated union
```typescript
type Result<T, E = Error> =
  | { ok: true; value: T }
  | { ok: false; error: E }

const ok = <T,>(value: T): Result<T, never> => ({ ok: true, value })
const err = <E,>(error: E): Result<never, E> => ({ ok: false, error })

function parseAge(s: string): Result<number, 'NaN' | 'Negative'> {
  const n = Number(s)
  if (Number.isNaN(n)) return err('NaN')
  if (n < 0) return err('Negative')
  return ok(n)
}

const r = parseAge('42')
if (r.ok) console.log(r.value)
else console.error(r.error)
```

### neverthrow library
```typescript
import { Result, ok, err, ResultAsync } from 'neverthrow'

const fetchUser = (id: string): ResultAsync<User, 'NotFound' | 'Network'> =>
  ResultAsync.fromPromise(
    fetch(`/api/users/${id}`).then(r => r.ok ? r.json() : Promise.reject('NotFound')),
    (e): 'NotFound' | 'Network' => e === 'NotFound' ? 'NotFound' : 'Network',
  )

await fetchUser('u1')
  .map(u => u.email)
  .mapErr(e => `failed: ${e}`)
  .match(
    email => console.log(email),
    err => console.error(err),
  )
```

### Effect TS (richer)
```typescript
import { Effect, pipe } from 'effect'

const parseJSON = (s: string) =>
  Effect.try({
    try: () => JSON.parse(s),
    catch: () => new Error('InvalidJSON'),
  })

const program = pipe(
  parseJSON('{"x":1}'),
  Effect.map((o: { x: number }) => o.x * 2),
  Effect.catchAll(e => Effect.succeed(0)),
)
Effect.runPromise(program).then(console.log)  // 2
```

### Rust (canonical)
```rust
fn divide(a: i32, b: i32) -> Result<i32, &'static str> {
    if b == 0 { Err("division by zero") } else { Ok(a / b) }
}

fn pipeline() -> Result<i32, &'static str> {
    let x = divide(10, 2)?;        // ? propagates Err
    let y = divide(x, 0)?;
    Ok(y)
}
```

### Validation accumulation (multiple errors)
```typescript
type Validated<T, E> = { ok: true; value: T } | { ok: false; errors: E[] }

const combine = <T, E>(rs: Result<T, E>[]): Validated<T[], E> => {
  const errs: E[] = []
  const vals: T[] = []
  for (const r of rs) r.ok ? vals.push(r.value) : errs.push(r.error)
  return errs.length ? { ok: false, errors: errs } : { ok: true, value: vals }
}
```

### Match helper
```typescript
function match<T, E, R>(r: Result<T, E>, on: { ok: (v: T) => R; err: (e: E) => R }): R {
  return r.ok ? on.ok(r.value) : on.err(r.error)
}
```

## 매 결정 기준
| 상황 | Approach |
|---|---|
| Recoverable error, type-safety 중요 | Result type |
| Truly unrecoverable (bug, OOM) | throw / panic |
| Multiple errors 누적 | Validated / Either with NonEmptyArray |
| Async + retry + interrupt | Effect TS |
| Simple library, no dep | hand-rolled discriminated union |
| Existing throw-based API | wrap with try/catch → Result |

**기본값**: 매 domain layer 는 Result, infrastructure boundary 에서 unwrap → throw 변환.

## 🔗 Graph
- 부모: [[Error Handling]] · [[Discriminated_Unions|Discriminated Unions]]
- 변형: [[Effect TS]]
- 응용: [[Zod 런타임 유효성 검사 통합]] · [[API 응답 및 에러 핸들링 아키텍처]]
- Adjacent: [[Type Theory]] · [[Functional Programming]]

## 🤖 LLM 활용
**언제**: 매 explicit error path, validation pipeline, FP-style composition, "this can fail" type-level documentation.
**언제 X**: 매 trivial script, throw 가 더 idiomatic 한 case (e.g. assertion, programmer error).

## ❌ 안티패턴
- **`unwrap()` 의 production**: 매 `Result` 의 의도 의 부정. 매 explicit `match` / `mapErr`.
- **`Result<T, Error>` 의 generic**: 매 specific tagged union (`'NotFound' | 'Conflict'`) 가 useful.
- **Mixed throw + Result**: layer 의 inconsistent → caller 의 confusing. 매 boundary 의 명확.
- **Async 에 raw Promise<Result>**: rejection 도 발생 → 매 ResultAsync / Effect 가 안전.

## 🧪 검증 / 중복
- Verified (Rust std::result docs, neverthrow README, Effect TS docs 3.x, "Domain Modeling Made Functional" Wlaschin).
- 신뢰도 A.

## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — Result patterns (TS, neverthrow, Effect, Rust) |

## 🛠️ 적용 사례 (Applied in summary)

<!-- CODE-GROUNDING:START -->
### 🔎 코드베이스 근거 (자동 추출 — E:\Wiki 레포)
**실제 구현/사용 위치:**
- `connectai/src/core/dataProcessor.ts:2` — * Aggregate result type definition

_자동 생성: code_grounding.mjs · 재실행 시 갱신됨_
<!-- CODE-GROUNDING:END -->
