Home > OS >  NGRX reducer does not throw incorrect assignment error
NGRX reducer does not throw incorrect assignment error

Time:10-13

I am working with ngrx for the first time. Normally in Typescript I get an incorrect assignment error for the following code because other is not specificed in the interface declaration:

interface IExample {
  count: number;
}

let initialState: IExample = { count: 0, other: '??????' };

// Type '{ count: number; other: string; }' is not assignable to type 'IExample'.
//   Object literal may only specify known properties, and 'other' does not exist in type 'IExample'.

But when I am creating a reducer the on associator (I think this is called an associator) does not throw this exception and maps other onto the return object.

interface IExample{
  count: number;
}

let initialState: IExample = { count: 0 };

const reducer = createReducer(
  initialState,
  on(add, (state, { payload }) => ({ 
    ...state,
    other: '??????' 
  })),
);

This is the on signature:

on<State, Creators extends readonly ActionCreator[]>(...args: [any, Creators, any, OnReducer<State extends infer S ? S : never, Creators>]): ReducerTypes<State, Creators>

How do I prevent these sorts of mistakes / how do I get these compilation errors showing again as they should ?

Note: "@ngrx/store": "^12.3.0",

CodePudding user response:

If you look at the reducer on function, you see that it does not specify the return type. And Typsecript is probably unable to determine it on its own. You can specify it manually and this should underline the error:

interface IExample{
  count: number;
}

let initialState: IExample = { count: 0 };

const reducer = createReducer(
  initialState,
  on(add, (state, { payload }): IExample => ({ 
    ...state,
    other: '??????' //should be underlined now
  })),
);

But you have to do this for every single on function which is unfortunate. Hopefully this will be fixed on NgRx side. But when playing with this I found other cases which allows you to bypass Typescript check, Object.assign is on of them.

const wrongIExample: IExample = Object.assign(initialState, { another: '????'});
// this is possible and does not throws error

Just to illustrate the fact that Typescript has its limitations still.

CodePudding user response:

This is a known issue, and sadly this needs to be fixed in TypeScript. As a workaround, you'll have to provide a return type to the on method.

const reducer = createReducer(
  initialState,
  on(add, (state, { payload }): IExample => ({ 
    ...state,
    other: '??????' 
    ~~~~~~ error
  })),
);

Because it's a common issue, it has its own lint rule at https://github.com/timdeschryver/eslint-plugin-ngrx/blob/main/docs/rules/on-function-explicit-return-type.md

  • Related