TypeScript 2.4 Generic Inference causing compilation errors

253 Views Asked by At

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'.
1

There are 1 best solutions below

2
On BEST ANSWER
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;