Q:

Type Safe Redux Reducer with Arguments

I'm trying to use typescript with react-redux, I'm having some issues with the reducer.  With the current setup I'm getting errors but I can't figure out why it's the case.  If I deviate from the approach in the redux documentation I am able to get something that works but it's repetitive. 
----- CODE: -----
I have three files in three separate directories which resemble:
store
|_actions
|   |_auth.ts  
|_reducers
|   |_auth.ts
|_types
    |_actionTypes.ts
    |_auth.ts

within actions/auth.ts file:
// actions/auth.ts
import { AuthActionTypes } from '../types/auth';
import * as actionTypes from '../types/actionTypes';

export const authStart = (): AuthActionTypes => {
    return {
        type: actionTypes. AUTH_START
    };
};

export const authSuccess = ( token: string, userId: string ): AuthActionTypes => {
    return {
        type: actionTypes. AUTH_SUCCESS,
        idToken: token,
        userId: userId
    };
};

export const authFail = ( error: Error ): AuthActionTypes => {
    return {
        type: actionTypes. AUTH_FAIL,
        error: error
    };
};

the reducers/auth.ts file:
// reducers/auth.ts
import * as actionTypes from '../types/actionTypes';
import { AuthState, AuthActionTypes } from '../types/auth';
import { updateObject } from '../utility';

const initialState: AuthState = {
    token: null,
    userId: null,
    error: null,
    loading: false,
    authRedirectPath: '/'
};

const authStart = ( state: AuthState, action: AuthActionTypes ) => {
    return updateObject( state, {error: null, loading: true })
};

const authSuccess = ( state: AuthState, action: AuthActionTypes ) => {
    return updateObject( state, { 
        token: action.idToken, // ##### this is giving me an error #####
        userId: action.userId, // ##### this is giving me an error #####
        error: null,
        loading: false
    });
};

const authFail = ( state: AuthState, action: AuthActionTypes ) => {
    return updateObject( state, {
        error: action.error, // ##### this is giving me an error #####
        loading: false
    });
};

const reducer = (state = initialState, action: AuthActionTypes): AuthState => {
    switch (action.type) {
        case actionTypes. AUTH_START: return authStart( state, action );
        case actionTypes. AUTH_SUCCESS: return authSuccess( state, action );
        case actionTypes. AUTH_FAIL: return authFail( state, action );
        default: 
            return state;
    };
};

export default reducer;

the types/auth.ts file:
// types/auth.ts
import * as actionTypes from './actionTypes';

export interface AuthState {
    token: null | string
    userId: null | string
    error: null | Error
    loading: boolean
    authRedirectPath: string
} 

interface AuthStart {
    type: typeof actionTypes. AUTH_START
}

interface AuthSuccess {
    type: typeof actionTypes. AUTH_SUCCESS;
    idToken: string;
    userId: string;
}

interface AuthFail {
    type: typeof actionTypes. AUTH_FAIL;
    error: Error;
}

export type AuthActionTypes = 
| AuthStart 
| AuthSuccess
| AuthFail;

for completeness the updateObject function found in utility.ts file used in reducers/auth.ts
export const updateObject = <T, U>(oldObject: T, updatedProperties: U): T => {
    return {
        ...oldObject,
        ...updatedProperties
    };
};

----- PROBLEM: -----
Within reducers/auth.ts the problem lies with the authSuccess arrow function.  I am presented with the following error message:
Property 'idToken' does not exist on type 'AuthActionTypes'. 
Property 'idToken' does not exist on type 'AuthStart'. 

We can see that both idToken and userId are defined in the interface.  I don't see why it would be referencing AuthStart and not AuthSuccess.  If I export the AuthSucess interface and declare it as the action type for that function then the error message is gone.  Is there any way of keeping action as AuthActionType or does it need to be explicitly declared as AuthSucess and the same for the others with this setup? 
Additionaly if I remove all the arrow functions and defined the logic directly in the case the error is no longer there.  That is if I have
// reducers/auth.ts
...
const reducer = (state = initialState, action: AuthActionTypes): AuthState => {
    switch (action.type) {
        ...
        case actionTypes. AUTH_SUCCESS: 
            return { 
               ...state, 
               token: action.idToken, 
               userId: action.userId, 
               error: null,
             };
...

Is there any way of keeping the setup that I have now without having to but the above logic directly in the swtich case, since the solution I have is easier for me to maintain? 

A:

Consider the definition of the AuthSuccess function on its own:
const authSuccess = ( state: AuthState, action: AuthActionTypes ) => {
    return updateObject( state, { 
        token: action.idToken, // ##### this is giving me an error #####
        userId: action.userId, // ##### this is giving me an error #####
        error: null,
        loading: false
    });
};

This definition suggests that action can be any of the AuthActionTypes, including AuthStart which lacks the idToken property.  Instead type the function as
const authSuccess = ( state: AuthState, action: AuthSuccess ) => {
    return updateObject( state, { 
        token: action.idToken, // ##### this is giving me an error #####
        userId: action.userId, // ##### this is giving me an error #####
        error: null,
        loading: false
    });
};

The switch statement in your reducer will allow typescript to refine the type of action passed to authSuccess as only AuthSuccess and not one of the other AuthActionTypes. 
This is the reason why inlining these functions works fine - the complier knows the action must be of type AuthSuccess in the case block so idToken and userId are valid.