I am seeing existing TypeScript code break due to the changes in generic inference.
Example:
interface Action {
type: string;
}
interface MyAction extends Action {
payload: string;
}
interface MyState {}
type Reducer<S> = <A extends Action>(state: S, action: A) => S;
const myReducer: Reducer<MyState> = (state: MyState, action: MyAction) => {
if (action.type === "MyActionType") {
return {};
}
else {
return {};
}
};
And the compilation error:
Error:(11, 7) TS2322:Type '(state: MyState, action: MyAction) => {}' is not assignable to type 'Reducer<MyState>'.
Types of parameters 'action' and 'action' are incompatible.
Type 'A' is not assignable to type 'MyAction'.
Type 'Action' is not assignable to type 'MyAction'.
Property 'payload' is missing in type 'Action'.
interface MyOtherAction {
type: 'MyOtherActionType'
foo: number
}
declare const state: State
declare const myOtherAction: MyOtherAction
// the following is a valid call according to myReducer's signature
myReducer(state, myOtherAction)
However the value you have assigned to myReducer
doesn't accept every type of action, therefore you get an error.
There's no reason to make the second parameter generic, as you aren't creating a constraint between two parameters/return value. Just do
type Reducer<S> = (state: S, action: Action) => S;