TypeScript FSA utilities for redux-saga

2.0.0 · active · verified Sun Apr 19

This package provides utility functions to seamlessly integrate asynchronous action creators from `typescript-fsa` with `redux-saga` worker sagas. Its primary function, `bindAsyncAction`, simplifies handling the lifecycle of async operations by automatically dispatching `started`, `done`, and `failed` actions around a saga's execution. This ensures strong type safety throughout the asynchronous flow when using `typescript-fsa`'s action patterns. The current stable version is 2.0.0, which notably requires `typescript-fsa` version 3.x.x. The project actively maintains compatibility with recent `redux-saga` releases, providing a reliable bridge between these two popular libraries for typed state management and side-effect handling.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates how to define an async action using `typescript-fsa` and then wrap a `redux-saga` worker with `bindAsyncAction` to automatically handle `started`, `done`, and `failed` dispatches, illustrating the type-safe flow.

import actionCreatorFactory from 'typescript-fsa';
import { SagaIterator } from 'redux-saga';
import { call } from 'redux-saga/effects';
import { bindAsyncAction } from 'typescript-fsa-redux-saga';

// actions.ts (excerpt)
const actionCreator = actionCreatorFactory('MY_APP');

export const doSomething =
  actionCreator.async<{foo: string},   // parameter type
                      {bar: number}    // result type
                     >('DO_SOMETHING');

// A mock API call function
async function fetchSomething(param: string): Promise<number> {
  console.log(`Simulating API call with: ${param}`);
  return new Promise(resolve => setTimeout(() => resolve(param.length * 10), 500));
}

// The worker saga wrapped by bindAsyncAction
const doSomethingWorker = bindAsyncAction(doSomething)(
  function* (params): SagaIterator<{bar: number}> {
    // `params` type is `{foo: string}`
    console.log(`Worker saga started with params:`, params);
    const result = yield call(fetchSomething, params.foo);
    console.log(`API call returned:`, result);
    return {bar: result};
  },
);

// A root saga that demonstrates calling the async worker
function* myRootSaga(): SagaIterator {
  console.log('Initiating doSomething action...');
  // Calling the worker directly. bindAsyncAction internally dispatches
  // doSomething.started, doSomething.done (or doSomething.failed if an error occurs).
  const result = yield call(doSomethingWorker, {foo: 'example_data'});
  console.log('doSomethingWorker completed with result:', result);

  try {
    console.log('Initiating another doSomething action (simulating potential error path)...');
    yield call(doSomethingWorker, {foo: 'error_case'}); // For demo, assuming this could lead to error
  } catch (e) {
    console.error('Caught an error in saga outside worker:', e); // Errors from worker are re-thrown by bindAsyncAction
  }
}

// To run this in a Redux Saga setup, you would typically pass `myRootSaga` to `sagaMiddleware.run`.
// Example (for conceptual understanding, not directly executable without Redux setup):
// import createSagaMiddleware from 'redux-saga';
// import { createStore, applyMiddleware } from 'redux';
// const sagaMiddleware = createSagaMiddleware();
// const store = createStore(() => ({}), applyMiddleware(sagaMiddleware));
// sagaMiddleware.run(myRootSaga);

view raw JSON →