当我从 Typescript 中的 createEntityAdapter 获取选择器时出现错误

Getting the Error when I get selectors from createEntityAdapter in Typescript

在开发一个简单的宠物项目时,我遇到了一个错误,不知道如何修复它。 我是 Typescript 的新手,通过消息错误判断错误在 TS 中。 将此代码段添加到文件 'apiSlice.ts'.

后出现错误消息
export const { selectAll: selectAllPizzas } = pizzasAdapter.getSelectors(
    state => selectPizzasData(state) ?? initialState
)

错误文本如下所示:

ERROR in src/features/api/apiSlice.ts:44:31
TS2345: Argument of type 'unknown' is not assignable to parameter of type '{ api: CombinedState<{ getPizzas: QueryDefinition<void, BaseQueryFn<string | FetchArgs, unknown,
 FetchBaseQueryError, {}, FetchBaseQueryMeta>, never, PizzaResponseType[], "api">; }, never, "api">; }'.
    42 | //
    43 | export const { selectAll: selectAllPizzas } = pizzasAdapter.getSelectors(
  > 44 |     state => selectPizzasData(state) ?? initialState
       |                               ^^^^^
    45 | )
    46 |

整个文件:(注意最后三行)

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import { createEntityAdapter, createSelector } from '@reduxjs/toolkit'

const pizzasAdapter = createEntityAdapter()
const initialState = pizzasAdapter.getInitialState()

interface PizzaResponseType {
    id: string
    name: string
    image: string
    price: number
    currencySign: string
    popularityPoint: number
    type: string
    description: string
    spec: string
}
export const apiSlice = createApi({
    reducerPath: 'api',
    baseQuery: fetchBaseQuery({ baseUrl: '' }),
    endpoints: builder => ({
        getPizzas: builder.query<PizzaResponseType[], void>({
            query: () => '/pizzas',
            transformResponse: (responseData: PizzaResponseType[]) => {
                pizzasAdapter.setAll(initialState, responseData)
                return responseData
            },
        }),
    }),
})

export const { useGetPizzasQuery } = apiSlice

export const selectPizzasResult = apiSlice.endpoints.getPizzas.select()

// console.log(selectPizzasResult)

export const selectPizzasData = createSelector(
    selectPizzasResult,
    pizzasResult => pizzasResult.data
)
//
export const { selectAll: selectAllPizzas } = pizzasAdapter.getSelectors(
    state => selectPizzasData(state) ?? initialState
)

RootState 是从 store.ts 文件中导入的,我在其中配置了 Redux Toolkit 文档中的商店。 store.ts 文件:

const store = configureStore({
    reducer: {
        pizzas:pizzaSlice,
        [apiSlice.reducerPath]: apiSlice.reducer,
    },
    middleware: getDefaultMiddleware => getDefaultMiddleware().concat(apiSlice.middleware),
})
export type RootState = ReturnType<typeof store.getState>
export default store

为参数中的状态插入了导入的 RootState 类型:

export const { selectAll: selectAllPizzas } = pizzasAdapter.getSelectors(
    (state: RootState) => selectPizzasData(state) ?? initialState
)

并且此更改没有任何作用。无论如何都会出现错误:

ERROR in src/features/api/apiSlice.ts:46:5
TS2345: Argument of type '(state: RootState) => EntityState<unknown> | PizzaResponseType[]' is not assignable to parameter of type '(state: { pizzas: EntityState<unknown>; api: CombinedState<{ getPizzas: Query
Definition<void, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, never, PizzaResponseType[], "api">; }, never, "api">; }) => EntityState<...>'.
  Type 'EntityState<unknown> | PizzaResponseType[]' is not assignable to type 'EntityState<unknown>'.
    Type 'PizzaResponseType[]' is missing the following properties from type 'EntityState<unknown>': ids, entities
    44 |
    45 | export const { selectAll: selectAllPizzas } = pizzasAdapter.getSelectors(
  > 46 |     (state: RootState) => selectPizzasData(state) ?? initialState
       |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    47 | )

如何解决?

如果您想 运行 宠物项目。遵循此 link:https://github.com/AlexKor-5/ReactPizzaApp_Ts/tree/27028d4275fef75a70eb6b0b4b129e5bf5997e78(但更改 apiSlice 文件的末尾,使其与 Stack Overflow 当前页面上显示的文件相对应)。 (src/features/api/apiSlice.ts )

您必须为 state 提供类型。

(state: RootState) => selectPizzasData(state) ?? initialState

根据@phry 的初始回复,我认为问题出在您的 transformResponse 功能上:

            transformResponse: (responseData: PizzaResponseType[]) => {
                pizzasAdapter.setAll(initialState, responseData)
                return responseData
            },

该代码有几个问题:

  • 您return使用原始responseData,它仍然是PizzaResponseType[]。这告诉 TS 结果是 also a PizzaResponseType[],而它 shouldEntityState<Pizza>.
  • 为了实现这一点,您需要 return 来自 pizzasAdapter.setAll() 的值。

我是这样重做的:

getPizzas: builder.query<EntityState<unknown>, void>({
            query: () => '/pizzas',
            transformResponse: (responseData: PizzaResponseType[]) => {
                return pizzasAdapter.setAll(initialState, responseData)
            },
        }),

加上这个片段:

export const { selectAll: selectAllPizzas } = pizzasAdapter.getSelectors(
    (state: RootState) => selectPizzasData(state) ?? initialState
)

所有这些更改后,错误消失了。