Skip to content

Commit 058955a

Browse files
committed
feat(action): add typesafe Error
[#33]
1 parent bf04aa3 commit 058955a

File tree

3 files changed

+72
-3
lines changed

3 files changed

+72
-3
lines changed

src/__snapshots__/redux-fluent.e2e.spec.ts.snap

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,31 @@ Object {
1010
],
1111
}
1212
`;
13+
14+
exports[`redux-fluent E2E should delete a todo 1`] = `
15+
Object {
16+
"todos": Array [
17+
Object {
18+
"id": "first-todo-id",
19+
"status": "pending",
20+
},
21+
],
22+
}
23+
`;
24+
25+
exports[`redux-fluent E2E should delete a todo 2`] = `
26+
Object {
27+
"todos": Array [
28+
Object {
29+
"id": "first-todo-id",
30+
"status": "pending",
31+
},
32+
],
33+
}
34+
`;
35+
36+
exports[`redux-fluent E2E should delete a todo 3`] = `
37+
Object {
38+
"todos": Array [],
39+
}
40+
`;

src/create-action/createAction.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// eslint-disable-next-line no-unused-vars
2-
import { FSA } from 'flux-standard-action';
2+
import { ErrorFSA, FSA } from 'flux-standard-action';
33

44

55
export interface ReduxFluentAction<
@@ -10,11 +10,21 @@ export interface ReduxFluentAction<
1010
type: T;
1111
}
1212

13+
export interface ReduxFluentActionError<
14+
T extends string = string,
15+
E extends Error = Error,
16+
M = void,
17+
> extends ErrorFSA<E, M> {
18+
type: T;
19+
}
20+
1321
type Formatter<T, R> = (rawPayload: any, rawMeta: any, T: T) => R;
1422
export type RFA<T extends string = string, P = any, M = any> = ReduxFluentAction<T, P, M>;
23+
export type RFAE<T extends string = string, P extends Error = Error, M = any> = ReduxFluentActionError<T, P, M>;
1524

1625
export interface ActionCreator<T extends string, P, M> {
1726
readonly type: T;
27+
<E extends Error = Error, RM = any>(rawPayload?: E, rawMeta?: RM): RFAE<T, E, M>
1828
<RP = any, RM = any>(rawPayload?: RP, rawMeta?: RM): RFA<T, P, M>;
1929
}
2030

src/redux-fluent.e2e.spec.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createStore } from 'redux';
2+
import { isError } from 'flux-standard-action';
23
import {
34
createAction,
45
combineReducers,
@@ -14,12 +15,19 @@ describe('redux-fluent E2E', () => {
1415

1516
const actions = {
1617
addTodo: createAction<'todos | add', Todo>('todos | add'),
18+
deleteTodo: createAction<'todos/:id | delete', Todo>('todos/:id | delete'),
1719
};
1820

1921
const todos = createReducer<'todos', Todo[]>('todos')
2022
.actions(
21-
ofType(actions.addTodo)
22-
.map(((state, action) => state.concat(action.payload))),
23+
ofType(actions.addTodo).map(
24+
((state, action) => state.concat(action.payload)),
25+
),
26+
ofType(actions.deleteTodo).map(
27+
((state, action) => (isError(action)
28+
? state
29+
: state.filter(({ id }) => id !== action.payload.id))),
30+
),
2331
)
2432
.default(() => []);
2533

@@ -37,4 +45,27 @@ describe('redux-fluent E2E', () => {
3745
store.getState(),
3846
).toMatchSnapshot();
3947
});
48+
49+
it('should delete a todo', () => {
50+
const store = createStore(rootReducer);
51+
const todo = {
52+
id: 'first-todo-id',
53+
status: 'pending',
54+
};
55+
56+
store.dispatch(actions.addTodo(todo));
57+
expect(
58+
store.getState(),
59+
).toMatchSnapshot();
60+
61+
store.dispatch(actions.deleteTodo(new Error('something went wrong')));
62+
expect(
63+
store.getState(),
64+
).toMatchSnapshot();
65+
66+
store.dispatch(actions.deleteTodo(todo));
67+
expect(
68+
store.getState(),
69+
).toMatchSnapshot();
70+
});
4071
});

0 commit comments

Comments
 (0)