0
# Type Helpers
1
2
Complete TypeScript type definitions and interfaces for building type-safe Redux applications with action creators, reducers, and state management utilities.
3
4
## Capabilities
5
6
### Core Types
7
8
Basic type definitions that form the foundation of the type system.
9
10
```typescript { .api }
11
/**
12
* Type representing action type constants (string literals)
13
*/
14
type TypeConstant = string;
15
16
/**
17
* Generic action interface with type property
18
*/
19
interface Action<TType extends TypeConstant = TypeConstant> {
20
type: TType;
21
}
22
23
/**
24
* Generic action creator function type
25
*/
26
type ActionCreator<TAction extends Action = Action> = (
27
...args: any[]
28
) => TAction;
29
30
/**
31
* Generic reducer function type
32
*/
33
type Reducer<TState, TAction extends Action> = (
34
state: TState | undefined,
35
action: TAction
36
) => TState;
37
```
38
39
### Action Types
40
41
Specialized action types for different payload and meta combinations.
42
43
```typescript { .api }
44
/**
45
* Action without payload (type only)
46
*/
47
type EmptyAction<TType extends TypeConstant> = Action<TType>;
48
49
/**
50
* Action with payload property
51
*/
52
interface PayloadAction<TType extends TypeConstant, TPayload> extends Action<TType> {
53
payload: TPayload;
54
}
55
56
/**
57
* Action with both payload and meta properties
58
*/
59
interface PayloadMetaAction<TType extends TypeConstant, TPayload, TMeta>
60
extends PayloadAction<TType, TPayload> {
61
meta: TMeta;
62
}
63
```
64
65
### Action Creator Types
66
67
Specialized action creator types corresponding to different action types.
68
69
```typescript { .api }
70
/**
71
* Action creator that produces EmptyAction
72
*/
73
type EmptyActionCreator<TType extends TypeConstant> = ActionCreator<EmptyAction<TType>>;
74
75
/**
76
* Action creator that produces PayloadAction
77
*/
78
type PayloadActionCreator<TType extends TypeConstant, TPayload> =
79
ActionCreator<PayloadAction<TType, TPayload>>;
80
81
/**
82
* Action creator that produces PayloadMetaAction
83
*/
84
type PayloadMetaActionCreator<TType extends TypeConstant, TPayload, TMeta> =
85
ActionCreator<PayloadMetaAction<TType, TPayload, TMeta>>;
86
```
87
88
### Type Metadata Interface
89
90
Interface for action creators with type metadata support.
91
92
```typescript { .api }
93
/**
94
* Interface representing type getter on action creator instance
95
*/
96
interface ActionCreatorTypeMetadata<TType extends TypeConstant> {
97
getType?(): TType;
98
}
99
```
100
101
### Utility Types
102
103
Advanced utility types for type inference and manipulation.
104
105
```typescript { .api }
106
/**
107
* Infers action union type from action creator or action creator map
108
*/
109
type ActionType<TActionCreatorOrMap extends any> =
110
TActionCreatorOrMap extends ActionCreator<TypeConstant>
111
? ReturnType<TActionCreatorOrMap>
112
: TActionCreatorOrMap extends Record<any, any>
113
? { [K in keyof TActionCreatorOrMap]: ActionType<TActionCreatorOrMap[K]> }[keyof TActionCreatorOrMap]
114
: never;
115
116
/**
117
* Infers state object type from reducer or reducer map
118
*/
119
type StateType<TReducerOrMap extends any> =
120
TReducerOrMap extends Reducer<any, any>
121
? ReturnType<TReducerOrMap>
122
: TReducerOrMap extends Record<any, any>
123
? { [K in keyof TReducerOrMap]: StateType<TReducerOrMap[K]> }
124
: never;
125
```
126
127
### Builder Types
128
129
Types used internally by action creator builders.
130
131
```typescript { .api }
132
/**
133
* Action builder type for createAction results
134
*/
135
type ActionBuilder<TType extends TypeConstant, TPayload = undefined, TMeta = undefined> =
136
TPayload extends undefined
137
? TMeta extends undefined
138
? EmptyAction<TType>
139
: never
140
: TMeta extends undefined
141
? PayloadAction<TType, TPayload>
142
: PayloadMetaAction<TType, TPayload, TMeta>;
143
144
/**
145
* Action creator builder interface for createAction
146
*/
147
interface ActionCreatorBuilder<TType extends TypeConstant, TPayload = undefined, TMeta = undefined> {
148
(): TPayload extends undefined
149
? TMeta extends undefined
150
? () => EmptyAction<TType>
151
: never
152
: never;
153
154
<P>(): TMeta extends undefined
155
? (payload: P) => PayloadAction<TType, P>
156
: never;
157
158
<P, M>(): (payload: P, meta: M) => PayloadMetaAction<TType, P, M>;
159
160
map<R, P>(
161
fn: (payload: P) => R
162
): TPayload extends undefined
163
? ActionCreatorBuilder<TType, R, TMeta>
164
: never;
165
}
166
167
/**
168
* Async action creator builder for createAsyncAction
169
*/
170
interface AsyncActionCreatorBuilder<
171
TRequestType extends TypeConstant,
172
TSuccessType extends TypeConstant,
173
TFailureType extends TypeConstant,
174
TCancelType extends TypeConstant = never
175
> {
176
request: ActionCreatorBuilder<TRequestType>;
177
success: ActionCreatorBuilder<TSuccessType>;
178
failure: ActionCreatorBuilder<TFailureType>;
179
cancel: TCancelType extends TypeConstant
180
? ActionCreatorBuilder<TCancelType>
181
: never;
182
}
183
```
184
185
### Module Augmentation Interface
186
187
Interface for augmenting the library with custom types.
188
189
```typescript { .api }
190
/**
191
* Interface for module augmentation - extend this in your app
192
* @example
193
* ```
194
* declare module 'typesafe-actions' {
195
* export type RootAction = ActionType<typeof import('./root-action').default>;
196
* export interface Types {
197
* RootAction: RootAction;
198
* }
199
* }
200
* ```
201
*/
202
interface Types {
203
RootAction: Action;
204
}
205
```
206
207
## Usage Examples
208
209
### Basic Type Usage
210
211
```typescript
212
import type {
213
Action,
214
ActionCreator,
215
PayloadAction,
216
EmptyAction
217
} from "typesafe-actions";
218
219
// Define action types
220
type IncrementAction = PayloadAction<'INCREMENT', number>;
221
type DecrementAction = EmptyAction<'DECREMENT'>;
222
type CounterAction = IncrementAction | DecrementAction;
223
224
// Define action creators with proper typing
225
const increment: ActionCreator<IncrementAction> = (payload: number) => ({
226
type: 'INCREMENT',
227
payload,
228
});
229
230
const decrement: ActionCreator<DecrementAction> = () => ({
231
type: 'DECREMENT',
232
});
233
```
234
235
### ActionType and StateType Usage
236
237
```typescript
238
import { createAction, createReducer } from "typesafe-actions";
239
import type { ActionType, StateType } from "typesafe-actions";
240
241
// Create action creators
242
const counterActions = {
243
increment: createAction('INCREMENT')<number>(),
244
decrement: createAction('DECREMENT')(),
245
reset: createAction('RESET')(),
246
};
247
248
// Infer action union type
249
type CounterAction = ActionType<typeof counterActions>;
250
// Result: ReturnType<typeof increment> | ReturnType<typeof decrement> | ReturnType<typeof reset>
251
252
// Create reducers
253
const rootReducer = {
254
counter: createReducer({ count: 0 })
255
.handleAction(counterActions.increment, (state, action) => ({
256
count: state.count + action.payload,
257
}))
258
.handleAction(counterActions.decrement, (state) => ({
259
count: state.count - 1,
260
}))
261
.handleAction(counterActions.reset, () => ({ count: 0 })),
262
263
user: createReducer({ name: '', email: '' })
264
.handleAction(setUser, (state, action) => action.payload),
265
};
266
267
// Infer root state type
268
type RootState = StateType<typeof rootReducer>;
269
// Result: { counter: { count: number }, user: { name: string, email: string } }
270
```
271
272
### Module Augmentation
273
274
```typescript
275
// In your application's type definitions file
276
import { ActionType } from 'typesafe-actions';
277
278
declare module 'typesafe-actions' {
279
interface Types {
280
RootAction: ActionType<typeof rootActions>;
281
}
282
}
283
284
// Now you can use RootAction throughout your app
285
import type { RootAction } from 'typesafe-actions';
286
287
function handleAction(action: RootAction) {
288
// action is typed as your app's root action union
289
}
290
```
291
292
### Advanced Generic Usage
293
294
```typescript
295
import type {
296
ActionCreatorBuilder,
297
AsyncActionCreatorBuilder,
298
ActionCreatorTypeMetadata
299
} from "typesafe-actions";
300
301
// Generic action creator factory
302
function createTypedAction<T extends string>(type: T) {
303
return <P = undefined, M = undefined>(): ActionCreatorBuilder<T, P, M> => {
304
// Implementation would go here
305
return {} as ActionCreatorBuilder<T, P, M>;
306
};
307
}
308
309
// Generic async action factory
310
function createTypedAsyncAction<
311
R extends string,
312
S extends string,
313
F extends string
314
>(requestType: R, successType: S, failureType: F) {
315
return <RP = undefined, SP = undefined, FP = undefined>():
316
AsyncActionCreatorBuilder<R, S, F> => {
317
// Implementation would go here
318
return {} as AsyncActionCreatorBuilder<R, S, F>;
319
};
320
}
321
322
// Usage with full type inference
323
const typedAction = createTypedAction('TYPED_ACTION')<string, number>();
324
const result = typedAction('payload', 42);
325
// result is typed as PayloadMetaAction<'TYPED_ACTION', string, number>
326
```
327
328
### Type Guards and Narrowing
329
330
```typescript
331
import type { Action, PayloadAction, EmptyAction } from "typesafe-actions";
332
333
// Custom type guards
334
function isPayloadAction<T extends string, P>(
335
action: Action,
336
type: T
337
): action is PayloadAction<T, P> {
338
return action.type === type && 'payload' in action;
339
}
340
341
function isEmptyAction<T extends string>(
342
action: Action,
343
type: T
344
): action is EmptyAction<T> {
345
return action.type === type && !('payload' in action);
346
}
347
348
// Usage in reducers
349
function counterReducer(state = { count: 0 }, action: Action) {
350
if (isPayloadAction<'INCREMENT', number>(action, 'INCREMENT')) {
351
// TypeScript knows action.payload is number
352
return { count: state.count + action.payload };
353
}
354
355
if (isEmptyAction(action, 'DECREMENT')) {
356
// TypeScript knows action has no payload
357
return { count: state.count - 1 };
358
}
359
360
return state;
361
}
362
```
363
364
## Internal Utility Types
365
366
These types are used internally by the library but may be useful for advanced usage:
367
368
```typescript { .api }
369
/**
370
* Internal type for resolving types - ensures proper type resolution in action creators
371
*/
372
type ResolveType<T> = T extends (...args: any[]) => any ? ReturnType<T> : T;
373
374
/**
375
* Internal utility for excluding never types from unions
376
*/
377
type ExcludeNever<T> = T extends never ? never : T;
378
```