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}`)
  }
}, { 
  timeout: 30000,
  tags: ['data', 'async'] 
})

Handler Configuration

Type-safe handler configuration with comprehensive options.

Basic Handler Configuration

typescript
register.register('processPayment', paymentHandler, {
  priority: 100,           // Higher number = higher priority
  tags: ['payment', 'critical'],
  category: 'business-logic',
  once: false,            // Can be executed multiple times
  timeout: 5000           // 5 second timeout
})

Advanced Configuration

typescript
register.register('analyticsTracker', trackingHandler, {
  priority: 10,
  tags: ['analytics', 'tracking'],
  category: 'monitoring',
  once: false,
  timeout: 2000,
  debounce: 100,         // Debounce rapid calls
  throttle: 500,         // Throttle execution frequency
  environment: 'production',  // Only in production
  feature: 'analytics'   // Feature flag
})

Conditional Handler

typescript
register.register('featureHandler', handler, {
  priority: 50,
  condition: (payload, context) => {
    // Only execute if user is premium
    return context.user?.isPremium === true
  },
  tags: ['premium', 'feature']
})

Real-World Examples

Released under the Apache-2.0 License.