CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-typesafe-actions

Typesafe Action Creators for Redux / Flux Architectures in TypeScript

Pending
Overview
Eval results
Files

action-creators.mddocs/

Action Creators

Core action creation functionality providing type-safe action creators with payload and meta support, async action patterns, and reducer utilities for Redux/Flux architectures.

Capabilities

action

Creates a Flux Standard Action with type, payload, meta, and error properties.

/**
 * Flux standard action factory
 * @param type - Action type constant
 * @returns Action object with type property
 */
function action<T extends TypeConstant>(type: T): { type: T };

/**
 * Flux standard action factory with payload
 * @param type - Action type constant  
 * @param payload - Action payload
 * @returns Action object with type and payload properties
 */
function action<T extends TypeConstant, P>(type: T, payload: P): { type: T; payload: P };

/**
 * Flux standard action factory with payload and meta
 * @param type - Action type constant
 * @param payload - Action payload
 * @param meta - Action meta information
 * @returns Action object with type, payload, and meta properties
 */
function action<T extends TypeConstant, P, M>(
  type: T,
  payload: P, 
  meta: M
): { type: T; payload: P; meta: M };

/**
 * Flux standard action factory with error flag
 * @param type - Action type constant
 * @param payload - Payload (undefined for error actions)
 * @param meta - Meta information (undefined for simple error actions)
 * @param error - Error flag
 * @returns Action object with error flag set
 */
function action<T extends TypeConstant, E>(
  type: T,
  payload: undefined,
  meta: undefined,
  error: E
): { type: T; error: E };

/**
 * Flux standard action factory with meta and error
 * @param type - Action type constant
 * @param payload - Payload (undefined)
 * @param meta - Meta information
 * @param error - Error flag
 * @returns Action object with meta and error properties
 */
function action<T extends TypeConstant, M, E>(
  type: T,
  payload: undefined,
  meta: M,
  error: E
): { type: T; meta: M; error: E };

/**
 * Flux standard action factory with payload and error
 * @param type - Action type constant
 * @param payload - Payload
 * @param meta - Meta information (undefined)
 * @param error - Error flag
 * @returns Action object with payload and error properties
 */
function action<T extends TypeConstant, P, E>(
  type: T,
  payload: P,
  meta: undefined,
  error: E
): { type: T; payload: P; error: E };

/**
 * Flux standard action factory with payload, meta, and error
 * @param type - Action type constant
 * @param payload - Payload
 * @param meta - Meta information
 * @param error - Error flag
 * @returns Action object with all properties
 */
function action<T extends TypeConstant, P, M, E>(
  type: T,
  payload: P,
  meta: M,
  error: E
): { type: T; payload: P; meta: M; error: E };

Usage Examples:

import { action } from "typesafe-actions";

// Simple action
const simpleAction = action('SIMPLE_ACTION');
// Result: { type: 'SIMPLE_ACTION' }

// Action with payload
const payloadAction = action('SET_USER', { id: 1, name: 'Alice' });
// Result: { type: 'SET_USER', payload: { id: 1, name: 'Alice' } }

// Action with payload and meta
const metaAction = action('LOG_EVENT', 'user_click', { timestamp: Date.now() });
// Result: { type: 'LOG_EVENT', payload: 'user_click', meta: { timestamp: 1234567890 } }

// Error action
const errorAction = action('API_ERROR', new Error('Failed'), undefined, true);
// Result: { type: 'API_ERROR', payload: Error, error: true }

createAction

Creates action creators with optional payload and meta creators for type-safe action creation.

/**
 * Create action creator with optional payload and meta creators
 * @param type - Action type constant
 * @returns ActionCreatorBuilder for fluent configuration
 */
function createAction<TType extends TypeConstant>(
  type: TType
): ActionCreatorBuilder<TType>;

/**
 * Create action creator with payload and meta creator functions
 * @param type - Action type constant
 * @param payloadCreator - Function to create payload
 * @param metaCreator - Function to create meta information
 * @returns Action creator function
 */
function createAction<
  TType extends TypeConstant,
  TCreatorPayload = undefined,
  TCreatorMeta = undefined,
  TArgs extends any[] = any[]
>(
  type: TType,
  payloadCreator?: (...args: TArgs) => TCreatorPayload,
  metaCreator?: (...args: TArgs) => TCreatorMeta
): (...args: TArgs) => ActionBuilder<TType, TCreatorPayload, TCreatorMeta>;

Usage Examples:

import { createAction } from "typesafe-actions";

// Simple action creator
const increment = createAction('INCREMENT')();
const result1 = increment();
// Result: { type: 'INCREMENT' }

// Action creator with payload
const setUser = createAction('SET_USER')<User>();
const result2 = setUser({ id: 1, name: 'Alice' });
// Result: { type: 'SET_USER', payload: { id: 1, name: 'Alice' } }

// Action creator with payload and meta
const logEvent = createAction('LOG_EVENT')<string, { timestamp: number }>();
const result3 = logEvent('user_click', { timestamp: Date.now() });
// Result: { type: 'LOG_EVENT', payload: 'user_click', meta: { timestamp: 1234567890 } }

// Action creator with creator functions
const createUserAction = createAction(
  'CREATE_USER',
  (name: string, email: string) => ({ name, email }),
  () => ({ timestamp: Date.now() })
);
const result4 = createUserAction('Alice', 'alice@example.com');
// Result: { type: 'CREATE_USER', payload: { name: 'Alice', email: 'alice@example.com' }, meta: { timestamp: 1234567890 } }

createCustomAction

Creates custom action creators using constructor function with injected type argument.

/**
 * Create custom action creator using constructor function with injected type argument
 * @param type - Action type constant
 * @param createHandler - Constructor function that receives arguments and returns action properties
 * @returns Custom action creator function with type metadata
 */
function createCustomAction<
  TType extends TypeConstant,
  TArgs extends any[] = [],
  TReturn extends any = {}
>(
  type: TType,
  createHandler?: (...args: TArgs) => TReturn
): ((...args: TArgs) => ResolveType<{ type: TType } & TReturn>) &
  ActionCreatorTypeMetadata<TType>;

Usage Examples:

import { createCustomAction } from "typesafe-actions";

// Custom action with additional properties
const customAction = createCustomAction('CUSTOM_ACTION', (payload: string) => ({
  payload,
  customProp: 'custom value',
  timestamp: Date.now(),
}));

const result = customAction('test payload');
// Result: { type: 'CUSTOM_ACTION', payload: 'test payload', customProp: 'custom value', timestamp: 1234567890 }

// Custom action mimicking FSA
const fsaLikeAction = createCustomAction('FSA_LIKE', (payload: any, error?: boolean) => ({
  ...(payload !== undefined && { payload }),
  ...(error && { error }),
}));

const result2 = fsaLikeAction({ data: 'test' });
// Result: { type: 'FSA_LIKE', payload: { data: 'test' } }

// Simple custom action without handler
const simpleCustomAction = createCustomAction('SIMPLE_CUSTOM');
const result3 = simpleCustomAction();
// Result: { type: 'SIMPLE_CUSTOM' }

createAsyncAction

Creates async action creator object containing request, success, failure, and optional cancel actions for async workflows.

/**
 * Create async action creator for request/success/failure pattern
 * @param requestType - Request action type
 * @param successType - Success action type
 * @param failureType - Failure action type
 * @returns AsyncAction object with request, success, failure properties
 */
function createAsyncAction<
  TRequestType extends TypeConstant,
  TSuccessType extends TypeConstant,
  TFailureType extends TypeConstant
>(
  requestType: TRequestType,
  successType: TSuccessType,
  failureType: TFailureType
): AsyncActionCreatorBuilder<TRequestType, TSuccessType, TFailureType>;

/**
 * Create async action creator with cancel action
 * @param requestType - Request action type
 * @param successType - Success action type
 * @param failureType - Failure action type
 * @param cancelType - Cancel action type
 * @returns AsyncAction object with request, success, failure, cancel properties
 */
function createAsyncAction<
  TRequestType extends TypeConstant,
  TSuccessType extends TypeConstant,
  TFailureType extends TypeConstant,
  TCancelType extends TypeConstant
>(
  requestType: TRequestType,
  successType: TSuccessType,
  failureType: TFailureType,
  cancelType: TCancelType
): AsyncActionCreatorBuilder<TRequestType, TSuccessType, TFailureType, TCancelType>;

Usage Examples:

import { createAsyncAction } from "typesafe-actions";

interface User {
  id: number;
  name: string;
}

// Basic async action
const fetchUser = createAsyncAction(
  'FETCH_USER_REQUEST',
  'FETCH_USER_SUCCESS',
  'FETCH_USER_FAILURE'
)<void, User, Error>();

// Usage in async flow
const requestAction = fetchUser.request();
// Result: { type: 'FETCH_USER_REQUEST' }

const successAction = fetchUser.success({ id: 1, name: 'Alice' });
// Result: { type: 'FETCH_USER_SUCCESS', payload: { id: 1, name: 'Alice' } }

const failureAction = fetchUser.failure(new Error('Network error'));
// Result: { type: 'FETCH_USER_FAILURE', payload: Error('Network error') }

// Async action with cancel
const fetchUserWithCancel = createAsyncAction(
  'FETCH_USER_REQUEST',
  'FETCH_USER_SUCCESS', 
  'FETCH_USER_FAILURE',
  'FETCH_USER_CANCEL'
)<void, User, Error, void>();

const cancelAction = fetchUserWithCancel.cancel();
// Result: { type: 'FETCH_USER_CANCEL' }

createReducer

Creates type-safe reducers with chainable API for handling actions.

/**
 * Create type-safe reducer with chainable API
 * @param initialState - Initial state value
 * @returns ReducerBuilder with handleAction and handleType methods
 */
function createReducer<TState, TRootAction extends Action = RootAction>(
  initialState: TState
): ReducerBuilder<TState, TRootAction>;

interface ReducerBuilder<TState, TRootAction extends Action> {
  /**
   * Handle specific action creator
   * @param actionCreator - Action creator to handle
   * @param handler - Reducer function for this action
   * @returns ReducerBuilder for chaining
   */
  handleAction<TAction extends TRootAction>(
    actionCreator: ActionCreator<TAction>,
    handler: (state: TState, action: TAction) => TState
  ): ReducerBuilder<TState, TRootAction>;

  /**
   * Handle specific action type
   * @param type - Action type to handle
   * @param handler - Reducer function for this action type
   * @returns ReducerBuilder for chaining
   */
  handleType<TType extends TRootAction['type']>(
    type: TType,
    handler: (
      state: TState,
      action: TRootAction extends Action<TType> ? TRootAction : never
    ) => TState
  ): ReducerBuilder<TState, TRootAction>;
}

Usage Examples:

import { createReducer, createAction } from "typesafe-actions";

interface CounterState {
  count: number;
}

const increment = createAction('INCREMENT')<number>();
const decrement = createAction('DECREMENT')();
const reset = createAction('RESET')();

// Create reducer with chained handlers
const counterReducer = createReducer<CounterState>({ count: 0 })
  .handleAction(increment, (state, action) => ({
    count: state.count + action.payload,
  }))
  .handleAction(decrement, (state) => ({
    count: state.count - 1,
  }))
  .handleAction(reset, () => ({
    count: 0,
  }));

// Usage
const newState1 = counterReducer({ count: 5 }, increment(3));
// Result: { count: 8 }

const newState2 = counterReducer({ count: 5 }, decrement());
// Result: { count: 4 }

// Handle multiple actions of same type
const multiReducer = createReducer({ value: 0 })
  .handleType('SET_VALUE', (state, action) => ({
    value: action.payload,
  }))
  .handleType('MULTIPLY_VALUE', (state, action) => ({
    value: state.value * action.payload,
  }));

Types

interface ActionCreatorBuilder<TType extends TypeConstant, TPayload = undefined, TMeta = undefined> {
  (): TPayload extends undefined
    ? TMeta extends undefined
      ? () => EmptyAction<TType>
      : never
    : never;

  <P>(): TMeta extends undefined
    ? (payload: P) => PayloadAction<TType, P>
    : never;

  <P, M>(): (payload: P, meta: M) => PayloadMetaAction<TType, P, M>;

  map<R, P>(
    fn: (payload: P) => R
  ): TPayload extends undefined
    ? ActionCreatorBuilder<TType, R, TMeta>
    : never;
}

interface AsyncActionCreatorBuilder<
  TRequestType extends TypeConstant,
  TSuccessType extends TypeConstant,
  TFailureType extends TypeConstant,
  TCancelType extends TypeConstant = never
> {
  request: ActionCreatorBuilder<TRequestType>;
  success: ActionCreatorBuilder<TSuccessType>;
  failure: ActionCreatorBuilder<TFailureType>;
  cancel: TCancelType extends TypeConstant 
    ? ActionCreatorBuilder<TCancelType>
    : never;
}

interface ReducerBuilder<TState, TRootAction extends Action> {
  handleAction<TAction extends TRootAction>(
    actionCreator: ActionCreator<TAction>,
    handler: (state: TState, action: TAction) => TState
  ): ReducerBuilder<TState, TRootAction>;

  handleType<TType extends TRootAction['type']>(
    type: TType,
    handler: (
      state: TState,
      action: TRootAction extends Action<TType> ? TRootAction : never
    ) => TState
  ): ReducerBuilder<TState, TRootAction>;
}

type ActionBuilder<TType extends TypeConstant, TPayload = undefined, TMeta = undefined> =
  TPayload extends undefined
    ? TMeta extends undefined
      ? EmptyAction<TType>
      : never
    : TMeta extends undefined
    ? PayloadAction<TType, TPayload>
    : PayloadMetaAction<TType, TPayload, TMeta>;

/**
 * Internal type for resolving types in createCustomAction
 */
type ResolveType<T> = T extends (...args: any[]) => any ? ReturnType<T> : T;

Install with Tessl CLI

npx tessl i tessl/npm-typesafe-actions

docs

action-creators.md

action-helpers.md

index.md

type-helpers.md

tile.json