Skip to content

Action Type System ​

Complete guide to the Context-Action framework's type system for actions, including ActionPayloadMap, type safety, and TypeScript integration.

Prerequisites ​

For action type definitions and context setup, see Basic Action Setup.

This document demonstrates type system patterns using the action setup:

ActionPayloadMap Interface ​

The foundation of type-safe action handling in the Context-Action framework.

Basic Action Mapping ​

typescript
// Using the AppActions pattern from setup guide
interface AppActions extends ActionPayloadMap {
  updateUser: { id: string; name: string; email: string };
  deleteUser: { id: string };
  saveUser: { name: string; email: string };
  refreshData: void;
}

Usage with ActionRegister ​

typescript
const register = new ActionRegister<AppActions>()

// Type-safe handler registration using setup pattern
register.register('updateUser', async (payload, controller) => {
  // payload is automatically typed as { id: string; name: string; email: string }
  await userService.update(payload.id, payload)
})

// Type-safe dispatch
await register.dispatch('updateUser', {
  id: '123',
  name: 'John Doe',
  email: 'john@example.com'
})

Pipeline Controller Types ​

Type-safe pipeline control for action handlers.

Basic Pipeline Control ​

typescript
// Handler with pipeline control
register.register('validateAndSave', async (payload, controller) => {
  // Modify payload before other handlers
  controller.modifyPayload(p => ({ ...p, validated: true }))
  
  // Get current payload state
  const currentPayload = controller.getPayload()
  
  // Stop execution early if needed
  if (!currentPayload.id) {
    controller.abort('Missing required ID')
    return
  }
  
  // Continue with validation
  const result = await validateUser(currentPayload)
  controller.setResult(result)
})

Early Return with Result ​

typescript
register.register('quickCheck', async (payload, controller) => {
  const cached = await getCachedResult(payload.id)
  
  if (cached) {
    // Return early with cached result, skip remaining handlers
    controller.return(cached)
    return
  }
  
  // Continue with expensive operation
  const result = await expensiveOperation(payload)
  controller.setResult(result)
})

Priority Jumping ​

typescript
register.register('conditionalHandler', async (payload, controller) => {
  if (payload.urgent) {
    // Skip to high-priority handlers
    controller.jumpToPriority(100)
    return
  }
  
  // Normal processing
  const result = await normalProcessing(payload)
  controller.setResult(result)
}, { priority: 50 })

Action Handler Types ​

Type-safe action handler definitions with full TypeScript support.

Store Integration Pattern ​

typescript
// Action handler with store integration
register.register('updateUserProfile', async (payload, controller) => {
  // Get current state from stores
  const currentUser = userStore.getValue()
  const currentSettings = settingsStore.getValue()
  
  try {
    // Business logic with type safety
    const updatedUser = { ...currentUser, ...payload }
    const result = await userService.update(updatedUser)
    
    // Update stores with new state
    userStore.setValue(result.user)
    settingsStore.update(settings => ({
      ...settings,
      lastUpdated: result.timestamp
    }))
    
    // Set handler result
    controller.setResult({ success: true, user: result.user })
  } catch (error) {
    controller.abort(`Update failed: ${error.message}`)
  }
})

Async Handler with Error Handling ​

typescript
register.register('syncData', async (payload, controller) => {
  try {
    // Start async operation
    const syncResult = await dataSync.start(payload.endpoint)
    
    // Update progress
    controller.setResult({ phase: 'syncing', progress: 0 })
    
    // Monitor progress
    for await (const progress of syncResult.progressStream) {
      controller.setResult({ phase: 'syncing', progress: progress.percent })
    }
    
    // Complete with final result
    controller.setResult({ 
      phase: 'complete', 
      progress: 100, 
      data: syncResult.data 
    })
  } catch (error) {
    controller.abort(`Sync failed: ${error.message}`)
  }
}, {
  id: 'sync-data-handler',
  metadata: { domain: 'data', mode: 'async' }
})

Handler Configuration ​

Type-safe handler configuration with comprehensive options.

Basic Handler Configuration ​

typescript
register.register('processPayment', paymentHandler, {
  id: 'payment-handler',
  priority: 100,           // Higher number = higher priority
  once: false,            // Can be executed multiple times
  metadata: { domain: 'payment' }
})

Advanced Configuration ​

typescript
register.register('analyticsTracker', trackingHandler, {
  id: 'analytics-tracker',
  priority: 10,
  once: false,
  debounce: 100,         // Debounce rapid calls
  throttle: 500,         // Throttle execution frequency
  metadata: { domain: 'analytics' }
})

Conditional Handler ​

typescript
register.register('featureHandler', handler, {
  priority: 50,
  condition: payload => Boolean(payload),
  metadata: { feature: 'premium' }
})

Real-World Examples ​

Released under the Apache-2.0 License.