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

问题描述 投票:0回答:4

在开发一个简单的宠物项目时,我遇到了一个错误,但不知道如何修复它。 我是 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 | )

如何解决?

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

当我写下

<EntityState<PizzaResponseType>
时,它应该是怎样的。看例子:

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

我收到另一个错误:

TS2322: Type '(responseData: IPizzaType[]) => EntityState<unknown>' is not assignable to type '(baseQueryReturnV
alue: unknown, meta: FetchBaseQueryMeta | undefined, arg: void) => EntityState<IPizzaType> | Promise<EntityState
<IPizzaType>>'.
  Type 'EntityState<unknown>' is not assignable to type 'EntityState<IPizzaType> | Promise<EntityState<IPizzaTyp
e>>'.
    Type 'EntityState<unknown>' is not assignable to type 'EntityState<IPizzaType>'.
      Type 'unknown' is not assignable to type 'IPizzaType'.
    28 |         getPizzas: builder.query<EntityState<IPizzaType>, void>({
    29 |             query: () => '/pizzas',
  > 30 |             transformResponse: (responseData: IPizzaType[]) => {
       |             ^^^^^^^^^^^^^^^^^
    31 |                 return pizzasAdapter.setAll(pizzaInitialState, responseData)
    32 |             },
    33 |         }),

又出什么问题了?

reactjs typescript redux redux-toolkit
4个回答
3
投票

您必须给出

state
的类型。

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

2
投票

根据 @phry 的最初回复,我认为问题是你的

transformResponse
函数:

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

该代码有几个问题:

  • 您将返回 原始
    responseData
    ,它仍然是
    PizzaResponseType[]
    。这告诉 TS 结果是 also a
    PizzaResponseType[]
    ,而它应该
    EntityState<Pizza>
  • 为了实现这一点,您需要从
    pizzasAdapter.setAll()
    返回值。

1
投票

我是这样重做的:

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
)

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


0
投票

如果有人遇到同样的问题...

interface PizzaResponseType {
  ...
}

const pizzasAdapter = createEntityAdapter<PizzaResponseType>()
const initialState = pizzasAdapter.getInitialState<PizzaResponseType[]>([])
type PizzasState = typeof inititalState

// apiSlice
// endpoints

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

export const selectPizzasData = createSelector(
    selectPizzasResult,
    pizzasResult => pizzasResult.data
) 

export const { selectAll: selectAllPizzas } = pizzasAdapter.getSelectors<RootState>(
    (state) => selectPizzasData(state) ?? initialState
)
© www.soinside.com 2019 - 2024. All rights reserved.