I have a redux style reducer (I'm using ngrx) that is returning a specific type. When I use the spread operator in my return object, the typescript linter is not catching invalid properties.
Here is my interface:
interface MyState {
firstName: string;
lastName: string;
age: number;
}
Here is my reducer. Action
is an ngrx action:
function reducer(state = initialState, action: Action): MyState {
switch (action.type) {
case Actions.COOL_ACTION:
return {
...state,
propertyDoesNotExist: action.payload, // <- no error
};
default:
return state;
}
}
I would expect that propertyDoesNotExist
would be flagged, but it is not. I've tried casting <CalendarState>
the return object, the state property ...(<CalendarState>state)
and using the as
alias, but it doesn't help.
It's like the spread operator messes up the types.
By using ...state
, the returned expression is no longer an object literal, and TypeScript won't complain if it's a subtype of the return type (i.e. has extra properties). I ran into this problem myself and wrote a little helper function to signal extra properties:
const applyChanges = <S, K extends keyof S>(state : S, changes : Pick<S, K>) : S =>
Object.assign({}, state, changes);
(using Object.assign
instead of spread operators because of this issue: https://github.com/Microsoft/TypeScript/issues/14409)
To use applyChanges
, simply replace
return {...state,
propertyDoesNotExist: action.payload, // <- no error
};
with
return applyChanges(state, {
propertyDoesNotExist: action.payload, // <- error
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With