Skip to content

Commit

Permalink
fix(store): adjust types to allow a generic reducer (#2996)
Browse files Browse the repository at this point in the history
Closes #2982
  • Loading branch information
timdeschryver authored Apr 19, 2021
1 parent cdb5bd5 commit 7da57bc
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 6 deletions.
19 changes: 18 additions & 1 deletion modules/store/spec/types/reducer_creator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { compilerOptions } from './utils';
describe('createReducer()', () => {
const expectSnippet = expecter(
(code) => `
import {createAction, createReducer, on, props} from '@ngrx/store';
import {createAction, createReducer, on, props, ActionCreator, ActionReducer} from '@ngrx/store';
${code}
`,
Expand Down Expand Up @@ -57,6 +57,23 @@ describe('createReducer()', () => {
);
`).toInfer('reducer', 'ActionReducer<number, Action>');
});

it('should support a generic reducer factory', () => {
expectSnippet(`
const creator = null as unknown as ActionCreator;
export function createGenericReducer<TState extends object>(initialState: TState): ActionReducer<TState> {
const reducer = createReducer(
initialState,
on(creator, (state, action) => {
return state ;
})
);
return reducer;
}
`).toSucceed();
});
});

describe('on()', () => {
Expand Down
11 changes: 6 additions & 5 deletions modules/store/src/reducer_creator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ export interface ReducerTypes<

// Specialized Reducer that is aware of the Action type it needs to handle
export interface OnReducer<State, Creators extends readonly ActionCreator[]> {
(state: State, action: ActionType<Creators[number]>): State extends object
? { [P in keyof State]: State[P] }
: State;
(state: State, action: ActionType<Creators[number]>): State;
}

/**
Expand All @@ -42,11 +40,14 @@ export interface OnReducer<State, Creators extends readonly ActionCreator[]> {
* ```
*/
export function on<State, Creators extends readonly ActionCreator[]>(
...args: [...creators: Creators, reducer: OnReducer<State, Creators>]
...args: [
...creators: Creators,
reducer: OnReducer<State extends infer S ? S : never, Creators>
]
): ReducerTypes<State, Creators> {
// This could be refactored when TS releases the version with this fix:
// https://github.com/microsoft/TypeScript/pull/41544
const reducer = args.pop() as OnReducer<State, Creators>;
const reducer = args.pop() as OnReducer<any, Creators>;
const types = (((args as unknown) as Creators).map(
(creator) => creator.type
) as unknown) as ExtractActionTypes<Creators>;
Expand Down

0 comments on commit 7da57bc

Please sign in to comment.