Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inferred generic type of reducers Number/String/Boolean instead of number/string/boolean #2966

Closed
lephyrus opened this issue Mar 10, 2021 · 1 comment · Fixed by #2967
Closed

Comments

@lephyrus
Copy link

lephyrus commented Mar 10, 2021

When the state is a number, string or boolean, and the reducer function uses no parameters (() => newState), the generic type of the action reducer is wrongly inferred to be Number, String or Boolean.

This leads to Typescript errors either in createReducer() itself (depending on the order or the action reducers) or later on.

This was not an issue in @ngrx/store v10 - I hit this as I've upgraded to v11.

Minimal reproduction of the bug/regression with instructions:

Reproduction in the Typescript playground.

import { Action, ActionReducer, createAction, createReducer, on, props } from '@ngrx/store';

const initialState: number = 0;

const setAction = createAction('set', props<{ value: number }>());
const resetAction = createAction('reset');

export const failingReducer = createReducer(
  initialState,
  on(setAction, (_state, { value }) => value),  // Typescript error
  on(resetAction, () => initialState),
);

export const workingReducer = createReducer(
  initialState,
  on(resetAction, () => initialState),
  on(setAction, (_state, { value }) => value),
);

export const expectedActionReducer: ActionReducer<number, Action> = workingReducer;  // Typescript error
export const actualActionReducer: ActionReducer<Number, Action> = workingReducer;

Expected behavior:

If the state is number, string, or boolean, reducers' inferred generic type should be the same, even if there is a "reset-style" action reducer.

Versions of NgRx, Angular, Node, affected browser(s) and operating system(s):

NgRx: 11.0.1
Typescript: 4.1.5 / 4.2.3

Other information:

The workaround is to add the state argument to the reducer function even though it is not needed:

export const reducer = createReducer(
  initialState,
  on(setAction, (_state, { value }) => value),
  on(resetAction, (_state) => initialState),
);

// works!
export const expectedActionReducer: ActionReducer<number, Action> = reducer;

I would be willing to submit a PR to fix this issue

[ ] Yes (Assistance is provided if you need help submitting a pull request)
[X] No

@lephyrus lephyrus changed the title Ordering of on() reducers in createReducer() params can lead to type error Generic type of reducers Number/String/Boolean instead of number/string/boolean Mar 10, 2021
@lephyrus lephyrus changed the title Generic type of reducers Number/String/Boolean instead of number/string/boolean Inferred generic type of reducers Number/String/Boolean instead of number/string/boolean Mar 10, 2021
brandonroberts pushed a commit that referenced this issue Mar 12, 2021
@parloti
Copy link

parloti commented Apr 1, 2021

Now I can no longer use on() with a generic state. Apparently, problem with type inference.

Play

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants