useReducer cannot use object.attr as switch case in typescript?

I’m trying to combine switch case String into an object, but somehow typescript is mis-interpreting the switch case in useReducer:

Before version, this works fine:

export const LOGIN_USER = "LOGIN_USER";
export const LOGOUT_USER = "LOGOUT_USER";

export type AuthActionType = LogInUser | LogOutUser;

type LogInUser = { type: typeof LOGIN_USER; payload: User }; // <- notice this
type LogOutUser = { type: typeof LOGOUT_USER };

export default function authReducer(
  state: AuthStateType,
  action: AuthActionType
) {
  switch (action.type) {
    case LOGIN_USER: {
      return {
        ...state,
        user: {
          username: action.payload.username, // <- correctly inferring action.payload.username 
          password: action.payload.password
        }
      };
    }

    case LOGOUT_USER: {
      return {
        ...state,
        user: null
      };
    }

    default: {
      return state;
    }
  }
}

However this breaks, after putting the switch case into an object:

export const AUTH = {
  LOGIN_USER: "LOGIN_USER",
  LOGOUT_USER: "LOGOUT_USER"
};

export type AuthActionType = LogInUser | LogOutUser;

type LogInUser = { type: typeof AUTH.LOGIN_USER; payload: User };  // <- notice this
type LogOutUser = { type: typeof AUTH.LOGOUT_USER };

export default function authReducer(
  state: AuthStateType,
  action: AuthActionType
) {
  switch (action.type) {
    case LOGIN_USER: {
      return {
        ...state,
        user: {
          username: action.payload.username,  // <- error over here, cannot infer the correct case?
          password: action.payload.password
        }
      };
    }

    case LOGOUT_USER: {
      return {
        ...state,
        user: null
      };
    }

    default: {
      return state;
    }
  }
}

Only by changing the type definition from type: typeof LOGIN_USER to type: typeof AUTH.LOGIN_USER, typescript breaks the switch case, how’s this happenning?

Sandbox, please take a look at this minimum reproduced version.

>Solution :

You can use const assertions to let typescript not convert ('LOGIN_USER' to string)

export const AUTH = {
      LOGIN_USER: "LOGIN_USER",
      LOGOUT_USER: "LOGOUT_USER"
    } as const;

Leave a Reply