enum-driven-state-authoring | Skill Performance & Reviews | TopRankSkills

TopRank Skills

Home / Skills / tools / enum-driven-state-authoring

enum-driven-state-authoring

maintained by jul-sh

star 0 account_tree 0 verified_user MIT License
bolt View GitHub

name: enum-driven-state-authoring description: When writing new code, model state as sum types from the start. Apply when creating entities with distinct modes, phases, or lifecycle states.

Enum-Driven State: Authoring Guide

When writing new code, model state as sum types from the start. Don't create optional fields that depend on other fields.


Before You Write

Ask these questions about your data:

  1. What are the mutually exclusive states? (e.g., Loading, Success, Error)
  2. For each state, what data is required? (e.g., Success needs data, Error needs error)
  3. Is there any data shared across ALL states? (e.g., id, timestamp → keep on wrapper)

Decision Flow

Does this entity have distinct modes/phases/states?
  │
  ├─ YES → Define a sum type with one variant per state
  │         Each variant holds only its required data
  │
  └─ NO → A simple struct/class is fine
           But watch for optional fields creeping in later

Patterns to Apply

Async/Remote Data

// Start here, not with optional fields
type RemoteData<T> =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success'; data: T }
  | { status: 'error'; error: Error };

Polymorphic Entities

// When type determines structure, use enum not optionals
enum Shape {
    Circle { radius: f64 },
    Rectangle { width: f64, height: f64 },
}

Workflow/Lifecycle States

@dataclass
class Draft:
    content: str

@dataclass
class Published:
    content: str
    published_at: datetime
    url: str

@dataclass
class Archived:
    content: str
    archived_at: datetime
    reason: str

Article = Draft | Published | Archived

Connection/Session State

sealed interface ConnectionState {
    data object Disconnected : ConnectionState
    data class Connecting(val attempt: Int) : ConnectionState
    data class Connected(val socket: Socket) : ConnectionState
    data class Error(val reason: Throwable) : ConnectionState
}

Anti-Patterns to Avoid

Don't start with this:

interface User {
  id: string;
  status: 'guest' | 'registered' | 'premium';
  email?: string;           // only if registered/premium
  subscriptionId?: string;  // only if premium
  expiresAt?: Date;         // only if premium
}

Start with this:

type User =
  | { status: 'guest'; id: string }
  | { status: 'registered'; id: string; email: string }
  | { status: 'premium'; id: string; email: string; subscriptionId: string; expiresAt: Date };

Shared Data Pattern

When some fields exist on ALL variants, wrap them:

struct Event {
    id: Uuid,
    timestamp: DateTime,
    payload: EventPayload,  // The sum type
}

enum EventPayload {
    UserCreated { name: String },
    OrderPlaced { items: Vec<Item> },
    PaymentFailed { reason: String },
}

Checklist When Authoring

  • Identified all mutually exclusive states
  • Each state has a dedicated variant/case
  • Data lives INSIDE its variant, not as optional sibling
  • Shared fields are on a wrapper struct
  • No optional field depends on another field's value

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!

Skill Details

GitHub Stars 0
GitHub Forks 0
Created Jan 2026
Last Updated 6 months ago
tools tools architecture patterns

Related Skills

dagger-design-proposals
chevron_right
nestjs-expert
chevron_right
docker-expert
chevron_right
kafka-streams-topology
chevron_right
kafka-architecture
chevron_right

Build your own?

Join 12,000+ developers contributing to the Claude ecosystem.