Skip to content

Commit 98b74ad

Browse files
alex-okrushkotimdeschryver
authored andcommitted
feat(store): compile time errors when action creators being passed to dispatch without () (#2306)
1 parent de703f0 commit 98b74ad

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { expecter } from 'ts-snippet';
2+
import { compilerOptions } from './utils';
3+
4+
describe('Store', () => {
5+
const expectSnippet = expecter(
6+
code => `
7+
import { Store, createAction } '@ngrx/store';
8+
9+
const store = {} as Store<{}>;
10+
const fooAction = createAction('foo')
11+
12+
${code}
13+
`,
14+
compilerOptions()
15+
);
16+
17+
it('should not allow passing action creator function without calling it', () => {
18+
expectSnippet(`store.dispatch(fooAction);`).toFail(
19+
/is not assignable to type '"Functions are not allowed to be dispatched. Did you forget to call action creator function/
20+
);
21+
});
22+
});

modules/store/src/models.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ export const typePropertyIsNotAllowedMsg =
6565
'type property is not allowed in action creators';
6666
type TypePropertyIsNotAllowed = typeof typePropertyIsNotAllowedMsg;
6767

68+
export type FunctionIsNotAllowed<
69+
T,
70+
ErrorMessage extends string
71+
> = T extends Function ? ErrorMessage : T;
6872
/**
6973
* A function that returns an object in the shape of the `Action` interface. Configured using `createAction`.
7074
*/

modules/store/src/store.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Observable, Observer, Operator } from 'rxjs';
33
import { distinctUntilChanged, map, pluck } from 'rxjs/operators';
44

55
import { ActionsSubject } from './actions_subject';
6-
import { Action, ActionReducer } from './models';
6+
import { Action, ActionReducer, FunctionIsNotAllowed } from './models';
77
import { ReducerManager } from './reducer_manager';
88
import { StateObservable } from './state';
99

@@ -93,7 +93,13 @@ export class Store<T> extends Observable<T> implements Observer<Action> {
9393
return store;
9494
}
9595

96-
dispatch<V extends Action = Action>(action: V) {
96+
dispatch<V extends Action = Action>(
97+
action: V &
98+
FunctionIsNotAllowed<
99+
V,
100+
'Functions are not allowed to be dispatched. Did you forget to call action creator function?'
101+
>
102+
) {
97103
this.actionsObserver.next(action);
98104
}
99105

0 commit comments

Comments
 (0)