02.03.01 — The Result[T] type#
Source file:
src/ocarina/railway/result.py— zero dependencies.
Code#
from dataclasses import dataclass, field
from typing import TypeGuard, final
class _BaseResult:
"""Base class ensuring both Ok and Fail have error attribute for type narrowing."""
error: Exception | None
@final
@dataclass(frozen=True)
class Ok[T](_BaseResult):
value: T
error: None = None
@final
@dataclass(frozen=True)
class Fail(_BaseResult):
error: Exception = field(default_factory=lambda: Exception("Unknown error"))
type Result[T] = Ok[T] | Fail
def is_ok[T](result: Result[T]) -> TypeGuard[Ok[T]]:
return isinstance(result, Ok)
def is_fail[T](result: Result[T]) -> TypeGuard[Fail]:
return isinstance(result, Fail)Six design decisions, dissected#
1. _BaseResult as a common parent#
class _BaseResult:
error: Exception | NoneOne job: let mypy read result.error without narrowing first. Without the base, you’d have to write: