首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >“通知”类型的参数不能分配给类型为'Notifications[] \ Record<EntityId,Notifications>‘的参数

“通知”类型的参数不能分配给类型为'Notifications[] \ Record<EntityId,Notifications>‘的参数
EN

Stack Overflow用户
提问于 2021-04-03 14:28:07
回答 1查看 268关注 0票数 0

在使用Redux创建异步Thunk并使用said Thunk作为extraReducer时,我将面临这个问题。

当我像这样指定Return argumentThunk ArgumentThunkApiConfig时,它会从notificationsAdapter.upsertMany()行的问题标题中抛出错误

代码语言:javascript
复制
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>的商店)时,就没有错误了,所以我不确定我以前设置的值有什么问题。

代码语言:javascript
复制
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;
  }
);

这方面的代码可以找到这里

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-03 23:23:22

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

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

代码语言:javascript
复制
state.error = action.error.message as Error;

实际上,您应该通过使用空的聚结来将undefined替换为null,从而执行正确的类型。

代码语言:javascript
复制
state.error = action.error.message ?? null;

@Nadia的评论是正确的。upsertMany需要数组Notifications[]或键控对象Record<EntityId, Notifications>。您的fetchNotifications操作正在返回一个通知Notifications。您的client.get响应是any,所以您不会因为返回错误类型而产生任何错误。

当您移除类型时,您不会得到任何错误,因为现在您的fetchNotifications操作返回any

您希望确保正在返回数组Notifications[]

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

代码语言:javascript
复制
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][]>;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66932277

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档