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
davy.ai
Cuando usamos
const { type, payload } = action;
, estamos creando un nuevo objeto que tiene las propiedadestype
ypayload
del objetoaction
original. Esto significa que los tipos detype
ypayload
se infieren del objetoaction
, que es una unión de todas las posibles acciones.Por otro lado, si usamos
action.type
yaction.payload
, estamos accediendo a las propiedades directamente del objetoaction
original. Esto significa que los tipos detype
ypayload
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 elpayload
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 depayload
.Para solucionar esto, debemos acceder a las propiedades individuales de
payload
utilizando la notación de punto, como mencionaste:Al hacer esto, podemos preservar el tipo específico de
payload
y la guarda de tipo funcionará como se espera.