Typesafe Action Creators for Redux / Flux Architectures in TypeScript
—
Core action creation functionality providing type-safe action creators with payload and meta support, async action patterns, and reducer utilities for Redux/Flux architectures.
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 }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 } }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' }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' }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,
}));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