Skip to content

refactor: Add type constraints to ActionHandler and ActionProcessor#11

Merged
takeshishimada merged 2 commits intomainfrom
refactor/add-actionhandler-type-constraints
Oct 30, 2025
Merged

refactor: Add type constraints to ActionHandler and ActionProcessor#11
takeshishimada merged 2 commits intomainfrom
refactor/add-actionhandler-type-constraints

Conversation

@takeshishimada
Copy link
Copy Markdown
Contributor

Summary

Add explicit type constraints to ActionHandler and ActionProcessor to match Feature protocol requirements, ensuring type safety and consistency across the framework.

Problem

Currently, ActionHandler and ActionProcessor lack explicit type constraints:

// Current (missing constraints)
class ActionHandler<Action, State, ActionResult: Sendable>

// Feature protocol (has constraints)
protocol Feature: Sendable {
  associatedtype Action: Sendable     
  associatedtype State: AnyObjectassociatedtype ActionResult: Sendable}

This inconsistency:

  • Weakens type safety when using ActionHandler directly
  • Doesn't prevent common errors at compile time
  • Creates confusion about requirements

Changes

ActionHandler.swift

  • ✅ Add Action: Sendable constraint
  • ✅ Add State: AnyObject constraint
  • ✅ Add documentation explaining each constraint's purpose

ActionProcessor.swift

  • ✅ Add same constraints to ActionProcessor class
  • ✅ Add constraints to ActionExecution typealias
  • ✅ Add documentation explaining type safety guarantees

Type Constraints Added

public final class ActionHandler<
  Action: Sendable,        // ← NEW: Safe concurrent action dispatching
  State: AnyObject,         // ← NEW: Reference semantics for mutation
  ActionResult: Sendable
>

public typealias ActionExecution<
  Action: Sendable,         // ← NEW
  State: AnyObject,          // ← NEW
  ActionResult: Sendable
> = @MainActor (Action, State) async -> ActionTask<...>

Benefits

  1. Prevents value-type State errors

    // ❌ Now caught at compile time
    struct State { var count: Int }  // Error: State must be AnyObject
    
    // ✅ Correct
    @Observable final class State { var count: Int }
  2. Prevents non-Sendable Action data races

    // ❌ Now caught at compile time
    enum Action {
      case update(NonSendableData)  // Error: Action must be Sendable
    }
  3. Ensures consistency with Feature protocol

    • Same constraints everywhere
    • Clear type safety guarantees
    • Better developer experience

Impact

  • Non-breaking change
    • All existing code satisfies these constraints through Feature protocol
    • Tests remain unchanged and pass
  • Compile-time safety improvements
    • Catches errors earlier in development
    • Better type inference
  • Documentation improvements
    • Clear explanation of constraints

Test Results

  • ✅ All 255 tests pass
  • ✅ Build succeeds (1.17s)
  • ✅ SwiftLint clean
  • ✅ No behavior changes

🤖 Generated with Claude Code

Add explicit type constraints to match Feature protocol requirements,
ensuring type safety and preventing common errors.

Changes:
- Add Sendable constraint to Action type parameter
- Add AnyObject constraint to State type parameter
- Add Sendable constraint to ActionResult type parameter (already present)
- Update ActionExecution typealias with same constraints
- Add documentation explaining the purpose of each constraint

Benefits:
- Prevents using value-type State (wouldn't support mutation)
- Prevents using non-Sendable Actions (could cause data races)
- Ensures consistency with Feature protocol requirements
- Compile-time enforcement of concurrency safety

This is a non-breaking change as all existing usage already satisfies
these constraints through Feature protocol conformance.

All tests pass (255 tests). SwiftLint clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@takeshishimada takeshishimada merged commit 03deb48 into main Oct 30, 2025
8 checks passed
@takeshishimada takeshishimada deleted the refactor/add-actionhandler-type-constraints branch October 31, 2025 08:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant