Blog>
Snippets

Middleware Resiliency with TypeScript Advanced Types

Explores the use of TypeScript advanced types such as conditional types and mapped types to create middleware that's more resilient to changes.
import { Middleware } from 'redux';

// Define a conditional type for different action types
type ConditionalAction<T> = T extends { type: 'special' }
    ? { type: 'special', specialData: string }
    : { type: string, payload?: any };

// Middleware using conditional types to handle actions
class MiddlewareAPI<S> {
    dispatch: (action: any) => void;
    getState: () => S;
}

// A function generating middleware with advanced TypeScript types
function createMiddleware<S>(): Middleware<{}, S> {
    return ({ dispatch, getState }: MiddlewareAPI<S>) =>
        (next: (action: any) => void) =>
            (action: ConditionalAction<any>) => {
                // Conditional logic based on action type
                if (action.type === 'special') {
                    console.log('Handling special action:', action.specialData);
                }

                // Passing action to the next middleware or the reducer
                return next(action);
            };
}
This code defines a TypeScript conditional type 'ConditionalAction' to distinguish between a specialized action with known properties and a generic action. The createMiddleware function then generates a redux middleware that uses this conditional type to perform different operations based on the action type received. If the action is of type 'special', it handles it accordingly; otherwise, it passes the action to the next middleware or the reducer.