Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

129
Visualizações
Typescript reducer's switch case typeguard doesn't work with object spread

I have a reducer that does different actions depending on the action.type, actions payload is different for certain actions.

    export enum ActionType {
      UpdateEntireState = "UPDATE_ENTIRE_STATE",
      UpdateStateItem = "UPDATE_STATE_ITEM"
    }
    
    type TypeEditData = {
      id: string;
      name: string;
      surname: string;
      age: number;
    };
    
    export type State = TypeEditData[];
    export type Action = UpdateEntireState | UpdateStateItem;
    
    type UpdateEntireState = {
      type: ActionType.UpdateEntireState;
      payload: State;
    };
    
    type UpdateStateItem = {
      type: ActionType.UpdateStateItem;
      payload: { id: string; data: TypeEditData };
    };
    
    export function reducer(state: State, action: Action): State {
      const { type, payload } = action;
    
      switch (type) {
        case ActionType.UpdateEntireState: {
          return [...payload];
        }
        case ActionType.UpdateStateItem: {
          const person = state.filter((item) => item.id === payload.id);
          return [...state, person[0]];
        }
        default: {
          throw Error("Wrong type of action!");
        }
      }
    }

This code won't work, the errors will say that my action payload can be State or { id: string; data: TypeEditData }. However, if I access the payload property inside switch case using dot notation like so

return [...action.payload];

There won't be any errors and the type guard will work fine. How const { type, payload } = action; differs from action.type and action.payload in terms of types and why doesn't typeguard work with spread syntax?

TS version - 4.3.4

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

The issue is that you've defined payload before there was type information available on action, so it has the union type

State | {
    id: string;
    data: TypeEditData;
};

Define a local variable or simply use action.payload within each case statement and the compiler knows what type it has:

export function reducer(state: State, action: Action): State {
  // const { type, payload } = action;

  switch (action.type) {
    case ActionType.UpdateEntireState: {
      return [...action.payload];
    }
    case ActionType.UpdateStateItem: {
      const person = state.filter((item) => item.id === action.payload.id);
      return [...state, person[0]];
    }
    default: {
      throw Error("Wrong type of action!");
    }
  }
}

Variable type is established explicitly at declaration (e.g. const a: string) or implicitly at initialization (e.g. a = 4). Subsequent typeguard constructs are not used to re-evaluate the type of the variable. On the contrary, since the type of the variable is already defined at that point, that type is used to validate whether the later construct is valid for the variable.

about 4 years ago · Juan Pablo Isaza Relatório

0

Action interface by default comes with type property.

export interface Action {
    type: string;
}

If you can extend Action interface to add payload as array of objects then typescript wont throw you an error. Something like this, in your reducer function you can use like this

interface CustomAction extends Action{
    payload: Array<any>
}


export function reducer(state: State, action: CustomAction): State {
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda