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