es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

El typeguard del switch case del reductor de Typescript no funciona con el spread de objetos.

Tengo un reductor que realiza diferentes acciones dependiendo del action.type, la carga de acciones es diferente para ciertas acciones.

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("¡Tipo de acción incorrecto!");
    }
  }
}

“`
Este código no funcionará, los errores indicarán que mi carga de acción puede ser State o { id: string; data: TypeEditData }.
Sin embargo, si accedo a la propiedad de carga dentro del caso de cambio usando la notación de punto de la siguiente manera:

return […action.payload];

No habrá errores y la guarda de tipo funcionará correctamente.
¿En qué se diferencia const { type, payload } = action; de action.type y action.payload en términos de tipos y por qué la guarda de tipo no funciona con la sintaxis de expansión?

Versión de TS: 4.3.4

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Cuando usamos const { type, payload } = action;, estamos creando un nuevo objeto que tiene las propiedades type y payload del objeto action original. Esto significa que los tipos de type y payload se infieren del objeto action, que es una unión de todas las posibles acciones.

    Por otro lado, si usamos action.type y action.payload, estamos accediendo a las propiedades directamente del objeto action original. Esto significa que los tipos de type y payload se infieren en función de la acción específica que se utiliza en ese caso.

    La razón por la cual la guarda de tipo no funciona con la sintaxis de propagación es porque el operador de propagación expande un array u objeto en valores individuales. Cuando usamos la sintaxis de propagación en la propiedad payload, estamos creando esencialmente un nuevo array con el mismo tipo que el payload original, en lugar de acceder a las propiedades individuales de ese objeto. Esto significa que la guarda de tipo no puede discernir el tipo específico de payload.

    Para solucionar esto, debemos acceder a las propiedades individuales de payload utilizando la notación de punto, como mencionaste:

    case ActionType.UpdateEntireState: {
      return [...action.payload];
    }
    

    Al hacer esto, podemos preservar el tipo específico de payload y la guarda de tipo funcionará como se espera.

Comments are closed.