类型 'Notifications' 的参数不能分配给类型 'Notifications[] | Record<EntityId, Notifications>' 的参数



我在使用Redux Toolkit创建Async Thunk并将所述Thunk用作extraReducer时遇到了这个问题。

当我指定类似的Return argumentThunk ArgumentThunkApiConfig时,它会在notificationsAdapter.upsertMany():行抛出问题标题中的错误

export const fetchNotifications = createAsyncThunk<
Notifications,
void,
{ state: RootState }
>("notifications/fetchNotifications", async (_, { getState }) => {
const allNotifications = selectAllNotifications(getState());
const [latestNotification] = allNotifications;
const latestTimestamp = latestNotification ? latestNotification.date : "";
const response = await client.get(
`/fakeApi/notifications?since=${latestTimestamp}`
);
return response.notifications;
});
const notificationsSlice = createSlice({
name: "notifications",
initialState,
reducers: {
allNotificationsRead(state) {
Object.values(state.entities).forEach((notification) => {
notification && (notification.read = true);
});
},
},
extraReducers: (builder) => {
builder.addCase(fetchNotifications.pending, (state) => {
state.status = "loading";
});
builder.addCase(fetchNotifications.rejected, (state, action) => {
state.status = "failed";
state.error = action.error.message as Error;
});
builder.addCase(fetchNotifications.fulfilled, (state, action) => {
state.status = "succeeded";
Object.values(state.entities).forEach((notification) => {
notification && (notification.isNew = !notification.read);
});
notificationsAdapter.upsertMany(state, action.payload);
});
},
});

但是,当我从createAsyncThunk中删除类型并断言getState()RootState(它来自使用export type RootState = ReturnType<typeof store.getState>的存储(时,就不再有错误了,所以我不确定我之前设置的值有什么问题。

export const fetchNotifications = createAsyncThunk(
"notifications/fetchNotifications",
async (_, { getState }) => {
const allNotifications = selectAllNotifications(getState() as RootState);
const [latestNotification] = allNotifications;
const latestTimestamp = latestNotification ? latestNotification.date : "";
const response = await client.get(
`/fakeApi/notifications?since=${latestTimestamp}`
);
return response.notifications;
}
);

此代码可在此处找到。

您必须非常小心as断言,因为如果断言的内容被证明是不正确的,则会产生问题。例如,您的类型Errorstring | null,但action.error.messagestring | undefined。当它是undefined时会发生什么?

而不是坚持打字你有正确的类型:

state.error = action.error.message as Error;

实际上,您应该通过使用nullish合并将undefined替换为null:来强制使用正确的类型

state.error = action.error.message ?? null;

@Nadia的评论是正确的。CCD_ 17期望数组CCD_ 18或键控对象CCD_。您的fetchNotifications操作返回一个通知Notifications。你的client.get响应是any,所以你不会因为返回错误的类型而得到任何错误。

删除类型时不会出现任何错误,因为现在fetchNotifications操作返回any

您需要确保返回的是一个数组Notifications[]


在我看来,避免此类错误的最佳方法是拥有一个强类型的client,它可以根据端点返回正确的类型。

interface EndpointMap {
"/fakeApi/notifications": Notifications;
}
interface Client {
getOne<K extends keyof EndpointMap>(
endpoint: K,
id: string
): Promise<EndpointMap[K]>;
getMany<K extends keyof EndpointMap>(
endpoint: K,
args: Record<string, any>
): Promise<EndpointMap[K][]>;
}

最新更新