Skip to content

Commit

Permalink
feat(store): compile time errors when action creators being passed to…
Browse files Browse the repository at this point in the history
… dispatch without () (#2306)
  • Loading branch information
alex-okrushko authored and timdeschryver committed Jan 6, 2020
1 parent de703f0 commit 98b74ad
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 2 deletions.
22 changes: 22 additions & 0 deletions modules/store/spec/types/store.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { expecter } from 'ts-snippet';
import { compilerOptions } from './utils';

describe('Store', () => {
const expectSnippet = expecter(
code => `
import { Store, createAction } '@ngrx/store';
const store = {} as Store<{}>;
const fooAction = createAction('foo')
${code}
`,
compilerOptions()
);

it('should not allow passing action creator function without calling it', () => {
expectSnippet(`store.dispatch(fooAction);`).toFail(
/is not assignable to type '"Functions are not allowed to be dispatched. Did you forget to call action creator function/
);
});
});
4 changes: 4 additions & 0 deletions modules/store/src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ export const typePropertyIsNotAllowedMsg =
'type property is not allowed in action creators';
type TypePropertyIsNotAllowed = typeof typePropertyIsNotAllowedMsg;

export type FunctionIsNotAllowed<
T,
ErrorMessage extends string
> = T extends Function ? ErrorMessage : T;
/**
* A function that returns an object in the shape of the `Action` interface. Configured using `createAction`.
*/
Expand Down
10 changes: 8 additions & 2 deletions modules/store/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Observable, Observer, Operator } from 'rxjs';
import { distinctUntilChanged, map, pluck } from 'rxjs/operators';

import { ActionsSubject } from './actions_subject';
import { Action, ActionReducer } from './models';
import { Action, ActionReducer, FunctionIsNotAllowed } from './models';
import { ReducerManager } from './reducer_manager';
import { StateObservable } from './state';

Expand Down Expand Up @@ -93,7 +93,13 @@ export class Store<T> extends Observable<T> implements Observer<Action> {
return store;
}

dispatch<V extends Action = Action>(action: V) {
dispatch<V extends Action = Action>(
action: V &
FunctionIsNotAllowed<
V,
'Functions are not allowed to be dispatched. Did you forget to call action creator function?'
>
) {
this.actionsObserver.next(action);
}

Expand Down

0 comments on commit 98b74ad

Please sign in to comment.