0
# Action Creators
1
2
Core action creation functionality providing type-safe action creators with payload and meta support, async action patterns, and reducer utilities for Redux/Flux architectures.
3
4
## Capabilities
5
6
### action
7
8
Creates a Flux Standard Action with type, payload, meta, and error properties.
9
10
```typescript { .api }
11
/**
12
* Flux standard action factory
13
* @param type - Action type constant
14
* @returns Action object with type property
15
*/
16
function action<T extends TypeConstant>(type: T): { type: T };
17
18
/**
19
* Flux standard action factory with payload
20
* @param type - Action type constant
21
* @param payload - Action payload
22
* @returns Action object with type and payload properties
23
*/
24
function action<T extends TypeConstant, P>(type: T, payload: P): { type: T; payload: P };
25
26
/**
27
* Flux standard action factory with payload and meta
28
* @param type - Action type constant
29
* @param payload - Action payload
30
* @param meta - Action meta information
31
* @returns Action object with type, payload, and meta properties
32
*/
33
function action<T extends TypeConstant, P, M>(
34
type: T,
35
payload: P,
36
meta: M
37
): { type: T; payload: P; meta: M };
38
39
/**
40
* Flux standard action factory with error flag
41
* @param type - Action type constant
42
* @param payload - Payload (undefined for error actions)
43
* @param meta - Meta information (undefined for simple error actions)
44
* @param error - Error flag
45
* @returns Action object with error flag set
46
*/
47
function action<T extends TypeConstant, E>(
48
type: T,
49
payload: undefined,
50
meta: undefined,
51
error: E
52
): { type: T; error: E };
53
54
/**
55
* Flux standard action factory with meta and error
56
* @param type - Action type constant
57
* @param payload - Payload (undefined)
58
* @param meta - Meta information
59
* @param error - Error flag
60
* @returns Action object with meta and error properties
61
*/
62
function action<T extends TypeConstant, M, E>(
63
type: T,
64
payload: undefined,
65
meta: M,
66
error: E
67
): { type: T; meta: M; error: E };
68
69
/**
70
* Flux standard action factory with payload and error
71
* @param type - Action type constant
72
* @param payload - Payload
73
* @param meta - Meta information (undefined)
74
* @param error - Error flag
75
* @returns Action object with payload and error properties
76
*/
77
function action<T extends TypeConstant, P, E>(
78
type: T,
79
payload: P,
80
meta: undefined,
81
error: E
82
): { type: T; payload: P; error: E };
83
84
/**
85
* Flux standard action factory with payload, meta, and error
86
* @param type - Action type constant
87
* @param payload - Payload
88
* @param meta - Meta information
89
* @param error - Error flag
90
* @returns Action object with all properties
91
*/
92
function action<T extends TypeConstant, P, M, E>(
93
type: T,
94
payload: P,
95
meta: M,
96
error: E
97
): { type: T; payload: P; meta: M; error: E };
98
```
99
100
**Usage Examples:**
101
102
```typescript
103
import { action } from "typesafe-actions";
104
105
// Simple action
106
const simpleAction = action('SIMPLE_ACTION');
107
// Result: { type: 'SIMPLE_ACTION' }
108
109
// Action with payload
110
const payloadAction = action('SET_USER', { id: 1, name: 'Alice' });
111
// Result: { type: 'SET_USER', payload: { id: 1, name: 'Alice' } }
112
113
// Action with payload and meta
114
const metaAction = action('LOG_EVENT', 'user_click', { timestamp: Date.now() });
115
// Result: { type: 'LOG_EVENT', payload: 'user_click', meta: { timestamp: 1234567890 } }
116
117
// Error action
118
const errorAction = action('API_ERROR', new Error('Failed'), undefined, true);
119
// Result: { type: 'API_ERROR', payload: Error, error: true }
120
```
121
122
### createAction
123
124
Creates action creators with optional payload and meta creators for type-safe action creation.
125
126
```typescript { .api }
127
/**
128
* Create action creator with optional payload and meta creators
129
* @param type - Action type constant
130
* @returns ActionCreatorBuilder for fluent configuration
131
*/
132
function createAction<TType extends TypeConstant>(
133
type: TType
134
): ActionCreatorBuilder<TType>;
135
136
/**
137
* Create action creator with payload and meta creator functions
138
* @param type - Action type constant
139
* @param payloadCreator - Function to create payload
140
* @param metaCreator - Function to create meta information
141
* @returns Action creator function
142
*/
143
function createAction<
144
TType extends TypeConstant,
145
TCreatorPayload = undefined,
146
TCreatorMeta = undefined,
147
TArgs extends any[] = any[]
148
>(
149
type: TType,
150
payloadCreator?: (...args: TArgs) => TCreatorPayload,
151
metaCreator?: (...args: TArgs) => TCreatorMeta
152
): (...args: TArgs) => ActionBuilder<TType, TCreatorPayload, TCreatorMeta>;
153
```
154
155
**Usage Examples:**
156
157
```typescript
158
import { createAction } from "typesafe-actions";
159
160
// Simple action creator
161
const increment = createAction('INCREMENT')();
162
const result1 = increment();
163
// Result: { type: 'INCREMENT' }
164
165
// Action creator with payload
166
const setUser = createAction('SET_USER')<User>();
167
const result2 = setUser({ id: 1, name: 'Alice' });
168
// Result: { type: 'SET_USER', payload: { id: 1, name: 'Alice' } }
169
170
// Action creator with payload and meta
171
const logEvent = createAction('LOG_EVENT')<string, { timestamp: number }>();
172
const result3 = logEvent('user_click', { timestamp: Date.now() });
173
// Result: { type: 'LOG_EVENT', payload: 'user_click', meta: { timestamp: 1234567890 } }
174
175
// Action creator with creator functions
176
const createUserAction = createAction(
177
'CREATE_USER',
178
(name: string, email: string) => ({ name, email }),
179
() => ({ timestamp: Date.now() })
180
);
181
const result4 = createUserAction('Alice', 'alice@example.com');
182
// Result: { type: 'CREATE_USER', payload: { name: 'Alice', email: 'alice@example.com' }, meta: { timestamp: 1234567890 } }
183
```
184
185
### createCustomAction
186
187
Creates custom action creators using constructor function with injected type argument.
188
189
```typescript { .api }
190
/**
191
* Create custom action creator using constructor function with injected type argument
192
* @param type - Action type constant
193
* @param createHandler - Constructor function that receives arguments and returns action properties
194
* @returns Custom action creator function with type metadata
195
*/
196
function createCustomAction<
197
TType extends TypeConstant,
198
TArgs extends any[] = [],
199
TReturn extends any = {}
200
>(
201
type: TType,
202
createHandler?: (...args: TArgs) => TReturn
203
): ((...args: TArgs) => ResolveType<{ type: TType } & TReturn>) &
204
ActionCreatorTypeMetadata<TType>;
205
```
206
207
**Usage Examples:**
208
209
```typescript
210
import { createCustomAction } from "typesafe-actions";
211
212
// Custom action with additional properties
213
const customAction = createCustomAction('CUSTOM_ACTION', (payload: string) => ({
214
payload,
215
customProp: 'custom value',
216
timestamp: Date.now(),
217
}));
218
219
const result = customAction('test payload');
220
// Result: { type: 'CUSTOM_ACTION', payload: 'test payload', customProp: 'custom value', timestamp: 1234567890 }
221
222
// Custom action mimicking FSA
223
const fsaLikeAction = createCustomAction('FSA_LIKE', (payload: any, error?: boolean) => ({
224
...(payload !== undefined && { payload }),
225
...(error && { error }),
226
}));
227
228
const result2 = fsaLikeAction({ data: 'test' });
229
// Result: { type: 'FSA_LIKE', payload: { data: 'test' } }
230
231
// Simple custom action without handler
232
const simpleCustomAction = createCustomAction('SIMPLE_CUSTOM');
233
const result3 = simpleCustomAction();
234
// Result: { type: 'SIMPLE_CUSTOM' }
235
```
236
237
### createAsyncAction
238
239
Creates async action creator object containing request, success, failure, and optional cancel actions for async workflows.
240
241
```typescript { .api }
242
/**
243
* Create async action creator for request/success/failure pattern
244
* @param requestType - Request action type
245
* @param successType - Success action type
246
* @param failureType - Failure action type
247
* @returns AsyncAction object with request, success, failure properties
248
*/
249
function createAsyncAction<
250
TRequestType extends TypeConstant,
251
TSuccessType extends TypeConstant,
252
TFailureType extends TypeConstant
253
>(
254
requestType: TRequestType,
255
successType: TSuccessType,
256
failureType: TFailureType
257
): AsyncActionCreatorBuilder<TRequestType, TSuccessType, TFailureType>;
258
259
/**
260
* Create async action creator with cancel action
261
* @param requestType - Request action type
262
* @param successType - Success action type
263
* @param failureType - Failure action type
264
* @param cancelType - Cancel action type
265
* @returns AsyncAction object with request, success, failure, cancel properties
266
*/
267
function createAsyncAction<
268
TRequestType extends TypeConstant,
269
TSuccessType extends TypeConstant,
270
TFailureType extends TypeConstant,
271
TCancelType extends TypeConstant
272
>(
273
requestType: TRequestType,
274
successType: TSuccessType,
275
failureType: TFailureType,
276
cancelType: TCancelType
277
): AsyncActionCreatorBuilder<TRequestType, TSuccessType, TFailureType, TCancelType>;
278
```
279
280
**Usage Examples:**
281
282
```typescript
283
import { createAsyncAction } from "typesafe-actions";
284
285
interface User {
286
id: number;
287
name: string;
288
}
289
290
// Basic async action
291
const fetchUser = createAsyncAction(
292
'FETCH_USER_REQUEST',
293
'FETCH_USER_SUCCESS',
294
'FETCH_USER_FAILURE'
295
)<void, User, Error>();
296
297
// Usage in async flow
298
const requestAction = fetchUser.request();
299
// Result: { type: 'FETCH_USER_REQUEST' }
300
301
const successAction = fetchUser.success({ id: 1, name: 'Alice' });
302
// Result: { type: 'FETCH_USER_SUCCESS', payload: { id: 1, name: 'Alice' } }
303
304
const failureAction = fetchUser.failure(new Error('Network error'));
305
// Result: { type: 'FETCH_USER_FAILURE', payload: Error('Network error') }
306
307
// Async action with cancel
308
const fetchUserWithCancel = createAsyncAction(
309
'FETCH_USER_REQUEST',
310
'FETCH_USER_SUCCESS',
311
'FETCH_USER_FAILURE',
312
'FETCH_USER_CANCEL'
313
)<void, User, Error, void>();
314
315
const cancelAction = fetchUserWithCancel.cancel();
316
// Result: { type: 'FETCH_USER_CANCEL' }
317
```
318
319
### createReducer
320
321
Creates type-safe reducers with chainable API for handling actions.
322
323
```typescript { .api }
324
/**
325
* Create type-safe reducer with chainable API
326
* @param initialState - Initial state value
327
* @returns ReducerBuilder with handleAction and handleType methods
328
*/
329
function createReducer<TState, TRootAction extends Action = RootAction>(
330
initialState: TState
331
): ReducerBuilder<TState, TRootAction>;
332
333
interface ReducerBuilder<TState, TRootAction extends Action> {
334
/**
335
* Handle specific action creator
336
* @param actionCreator - Action creator to handle
337
* @param handler - Reducer function for this action
338
* @returns ReducerBuilder for chaining
339
*/
340
handleAction<TAction extends TRootAction>(
341
actionCreator: ActionCreator<TAction>,
342
handler: (state: TState, action: TAction) => TState
343
): ReducerBuilder<TState, TRootAction>;
344
345
/**
346
* Handle specific action type
347
* @param type - Action type to handle
348
* @param handler - Reducer function for this action type
349
* @returns ReducerBuilder for chaining
350
*/
351
handleType<TType extends TRootAction['type']>(
352
type: TType,
353
handler: (
354
state: TState,
355
action: TRootAction extends Action<TType> ? TRootAction : never
356
) => TState
357
): ReducerBuilder<TState, TRootAction>;
358
}
359
```
360
361
**Usage Examples:**
362
363
```typescript
364
import { createReducer, createAction } from "typesafe-actions";
365
366
interface CounterState {
367
count: number;
368
}
369
370
const increment = createAction('INCREMENT')<number>();
371
const decrement = createAction('DECREMENT')();
372
const reset = createAction('RESET')();
373
374
// Create reducer with chained handlers
375
const counterReducer = createReducer<CounterState>({ count: 0 })
376
.handleAction(increment, (state, action) => ({
377
count: state.count + action.payload,
378
}))
379
.handleAction(decrement, (state) => ({
380
count: state.count - 1,
381
}))
382
.handleAction(reset, () => ({
383
count: 0,
384
}));
385
386
// Usage
387
const newState1 = counterReducer({ count: 5 }, increment(3));
388
// Result: { count: 8 }
389
390
const newState2 = counterReducer({ count: 5 }, decrement());
391
// Result: { count: 4 }
392
393
// Handle multiple actions of same type
394
const multiReducer = createReducer({ value: 0 })
395
.handleType('SET_VALUE', (state, action) => ({
396
value: action.payload,
397
}))
398
.handleType('MULTIPLY_VALUE', (state, action) => ({
399
value: state.value * action.payload,
400
}));
401
```
402
403
## Types
404
405
```typescript { .api }
406
interface ActionCreatorBuilder<TType extends TypeConstant, TPayload = undefined, TMeta = undefined> {
407
(): TPayload extends undefined
408
? TMeta extends undefined
409
? () => EmptyAction<TType>
410
: never
411
: never;
412
413
<P>(): TMeta extends undefined
414
? (payload: P) => PayloadAction<TType, P>
415
: never;
416
417
<P, M>(): (payload: P, meta: M) => PayloadMetaAction<TType, P, M>;
418
419
map<R, P>(
420
fn: (payload: P) => R
421
): TPayload extends undefined
422
? ActionCreatorBuilder<TType, R, TMeta>
423
: never;
424
}
425
426
interface AsyncActionCreatorBuilder<
427
TRequestType extends TypeConstant,
428
TSuccessType extends TypeConstant,
429
TFailureType extends TypeConstant,
430
TCancelType extends TypeConstant = never
431
> {
432
request: ActionCreatorBuilder<TRequestType>;
433
success: ActionCreatorBuilder<TSuccessType>;
434
failure: ActionCreatorBuilder<TFailureType>;
435
cancel: TCancelType extends TypeConstant
436
? ActionCreatorBuilder<TCancelType>
437
: never;
438
}
439
440
interface ReducerBuilder<TState, TRootAction extends Action> {
441
handleAction<TAction extends TRootAction>(
442
actionCreator: ActionCreator<TAction>,
443
handler: (state: TState, action: TAction) => TState
444
): ReducerBuilder<TState, TRootAction>;
445
446
handleType<TType extends TRootAction['type']>(
447
type: TType,
448
handler: (
449
state: TState,
450
action: TRootAction extends Action<TType> ? TRootAction : never
451
) => TState
452
): ReducerBuilder<TState, TRootAction>;
453
}
454
455
type ActionBuilder<TType extends TypeConstant, TPayload = undefined, TMeta = undefined> =
456
TPayload extends undefined
457
? TMeta extends undefined
458
? EmptyAction<TType>
459
: never
460
: TMeta extends undefined
461
? PayloadAction<TType, TPayload>
462
: PayloadMetaAction<TType, TPayload, TMeta>;
463
464
/**
465
* Internal type for resolving types in createCustomAction
466
*/
467
type ResolveType<T> = T extends (...args: any[]) => any ? ReturnType<T> : T;
468
```