reactjs - Får fel när jag hämtar selektorer från createEntityAdapter i Typescript


När jag utvecklade ett enkelt hobbyprojekt stötte jag på ett fel, utan att veta hur jag skulle fixa det. Jag är ny på Typescript, och att döma av ett felmeddelande ligger misstaget i TS. Felmeddelandet visas efter att ha lagt till detta utdrag i filen 'apiSlice.ts'.

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

Feltexten ser ut så här:

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 |

Hela filen: (Fokusera på de sista tre raderna)

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 importerades från filen store.ts, där jag konfigurerade butiken som det stod i Redux Toolkit-dokumentationen. Filen 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

Den importerade RootState-typen sattes in för tillståndet i parametern:

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

och denna ändring gör inget. Felet visas ändå:

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 | )

Hur åtgärdar man det?

Om du vill köra husdjursprojektet. Följ denna länk: https://github.com/AlexKor-5/ReactPizzaApp_Ts/tree/27028d4275fef75a70eb6b0b4b129e5bf5997e78 (men ändra slutet av apiSlice-filen så att det motsvarar filen som visas på den aktuella sidan av Stack Overflow). (src/features/api/apiSlice.ts )

Också när jag skriver <EntityState<PizzaResponseType> hur det ska vara. Titta på exemplet:

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

Jag får ett annat fel:

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 |         }),

Vad är det som är fel igen?

Svar #1

Du måste ange en typ för state.

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

Svar #2

Följande på @phry:s initiala svar, jag tror problemet är din transformResponse-funktion:

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

Den koden har ett par problem:

  • Du returnerar den ursprungliga responseData, som fortfarande är en PizzaResponseType[]. Det säger till TS att resultatet också är en PizzaResponseType[], när det som det borde vara är ett EntityState<Pizza>.
  • För att få det att hända behöver du istället returnera värdet från pizzasAdapter.setAll().