我正在将我的 react 应用程序转换为 Typescript,但遇到了 reducer 中操作类型的问题。
我在使用 Discriminated Unions 时遇到错误,例如在操作 ADD_TO_CART 上,当我在 Discriminated Unions 中有多个声明时,它会向我显示错误
Property 'product' does not exist on type 'ICart | IProduct | { products: IProduct[]; } | IOrder'.
Property 'product' does not exist on type 'IProduct'.ts(2339)
当我删除所有其他操作类型并只保留 ADD_TO_CART 时,打字稿中的错误消失了。如何声明我的操作,使其不显示错误?
同样适用于其他类型,例如 GET_PRODUCTS,当我从 Discriminated Unions 中删除所有其他类型并只留下 GET_PRODUCTS 时,错误消失了,但是当我声明它显示的所有操作时:
Property 'products' does not exist on type 'ICart | IProduct | { products: IProduct[]; } | IOrder'.
Property 'products' does not exist on type 'ICart'.ts(2339)
export interface IArticle {
_id: string,
title: string,
shortDescription: string,
content: string,
author: string,
createdAt: Date,
updatedAt: Date,
}
export interface IProduct {
_id: string,
title: string,
category: string,
shortDescription: string,
description: string,
photo: {
fileName: string,
url: string,
},
createdAt: Date,
updatedAt: Date,
}
export interface ICart {
product: IProduct,
qty: number,
}
export interface IOrder {
nr: number,
products: object,
user: string | IUser,
status: string,
comment: string,
createdAt: Date,
updatedAt: Date,
}
我的减速机
import {
ADD_TO_CART, GET_PRODUCTS, DELETE_FROM_CART, ADD_ORDER, GET_ORDERS, GET_ONE_ORDER,
CLEAR_ONE_ORDER, ARCHIVE_ORDER, GET_ARCHIVED_ORDERS, GET_ONE_ARCHIVED_ORDER,
CLEAR_ONE_ARCHIVED_ORDER, GET_ORDERS_ADMIN, START_ORDER, GET_RECAP_ADMIN,
} from '../actions/types.action';
import { IProduct, IOrder, ICart } from '../declarations';
const initialState = {
products: [],
isLoading: true,
cart: {},
orders: [],
adminOrders: [],
recapLoading: true,
recapAdmin: null,
archivedOrders: [],
archivedOrdersLoading: true,
oneArchivedOrder: null,
oneArchivedOrderLoading: true,
cartLength: null,
oneOrder: null,
oneOrderLoading: true,
backdropOpen: false,
};
type ACTIONTYPE =
| { type: 'ADD_TO_CART'; payload: ICart }
| { type: 'GET_PRODUCTS'; payload: { products: IProduct[] } }
| { type: 'DELETE_FROM_CART'; payload: IProduct }
| { type: 'ADD_ORDER'; payload: null }
| { type: 'GET_ORDERS'; payload: null }
| { type: 'GET_ONE_ORDER'; payload: null }
| { type: 'CLEAR_ONE_ORDER'; payload: null }
| { type: 'ARCHIVE_ORDER'; payload: IOrder }
| { type: 'GET_ARCHIVED_ORDERS'; payload: null }
| { type: 'GET_ONE_ARCHIVED_ORDER'; payload: null }
| { type: 'CLEAR_ONE_ARCHIVED_ORDER'; payload: null }
| { type: 'GET_ORDERS_ADMIN'; payload: null }
| { type: 'START_ORDER'; payload: null }
| { type: 'GET_RECAP_ADMIN'; payload: null };
export default function (state = initialState, action: ACTIONTYPE) {
const { type, payload } = action;
switch (type) {
case ADD_TO_CART:
return {
...state,
cart: {
...state.cart,
[payload?.product?._id]: {
product: payload.product,
qty: payload.qty,
},
},
};
case DELETE_FROM_CART:
return {
...state,
cart: update(state.cart, {
$unset: [payload],
}),
};
case GET_PRODUCTS:
return {
...state,
products: payload.products,
isLoading: false,
};
case GET_RECAP_ADMIN:
return {
...state,
recapAdmin: payload,
recapLoading: false,
};
case ADD_ORDER:
return {
...state,
cart: {},
backdropOpen: false,
};
case START_ORDER:
return {
...state,
backdropOpen: true,
};
case GET_ORDERS:
return {
...state,
orders: payload,
isLoading: false,
};
case GET_ONE_ORDER:
return {
...state,
oneOrder: payload,
oneOrderLoading: false,
};
case CLEAR_ONE_ORDER:
return {
...state,
oneOrder: null,
oneOrderLoading: true,
};
case ARCHIVE_ORDER:
return {
...state,
orders: state.orders.filter((o) => o._id !== payload?._id),
isLoading: false,
};
case GET_ARCHIVED_ORDERS:
return {
...state,
archivedOrders: payload,
archivedOrdersLoading: false,
};
case GET_ONE_ARCHIVED_ORDER:
return {
...state,
oneArchivedOrder: payload,
oneArchivedOrderLoading: false,
};
case CLEAR_ONE_ARCHIVED_ORDER:
return {
...state,
oneArchivedOrder: null,
oneArchivedOrderLoading: true,
};
case GET_ORDERS_ADMIN:
return {
...state,
adminOrders: payload,
isLoading: false,
};
default:
return state;
}
}
答案 0 :(得分:2)
我们特别推荐not trying to create TS union types of your Redux actions。此外,您不必手动编写任何单独的动作创建者或动作类型,因为 our official Redux Toolkit package does all that work for you automatically。
因此,在这种情况下,最好的方法是使用 Redux Toolkit 的 createSlice
API 重写此逻辑,这将避免类型问题、简化逻辑并消除对所有这些手写操作的需要。