Skip to content

Commit 604577b

Browse files
committed
Fix a bug in the RTKQ selector typings causing bad state args
The `ReducerPath` type tries to extract the generic type for "the path of the reducer" arg from `EndpointDefinitions`. However, it looks like this was always off by one: getting the 4th arg instead of the actual 5th arg. This caused bad input to the generated selectors. That seems to have worked okay with Reselect 4.0 and its looser types, but caused problems when we updated to Reselect 4.1.x and its improved types. The `RootState` type collapsed down to an empty object, because there was no valid string to use as an object key. This fixes the bug and adds a typetest to verify that the selector types are carried through all the way.
1 parent 4bb0c5c commit 604577b

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-2
lines changed

packages/toolkit/src/query/endpointDefinitions.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,9 @@ export type QueryArgFrom<D extends BaseEndpointDefinition<any, any, any>> =
464464
export type ResultTypeFrom<D extends BaseEndpointDefinition<any, any, any>> =
465465
D extends BaseEndpointDefinition<any, any, infer RT> ? RT : unknown
466466

467-
export type ReducerPathFrom<D extends EndpointDefinition<any, any, any, any>> =
468-
D extends EndpointDefinition<any, any, any, infer RP> ? RP : unknown
467+
export type ReducerPathFrom<
468+
D extends EndpointDefinition<any, any, any, any, any>
469+
> = D extends EndpointDefinition<any, any, any, any, infer RP> ? RP : unknown
469470

470471
export type TagTypesFrom<D extends EndpointDefinition<any, any, any, any>> =
471472
D extends EndpointDefinition<any, any, infer RP, any> ? RP : unknown
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
2+
3+
import { createSelector, configureStore } from '@reduxjs/toolkit'
4+
import { expectExactType } from './helpers'
5+
6+
describe('buildSelector', () => {
7+
test.skip('buildSelector typetest', () => {
8+
interface Todo {
9+
userId: number
10+
id: number
11+
title: string
12+
completed: boolean
13+
}
14+
15+
type Todos = Array<Todo>
16+
17+
const exampleApi = createApi({
18+
reducerPath: 'api',
19+
baseQuery: fetchBaseQuery({
20+
baseUrl: 'https://jsonplaceholder.typicode.com',
21+
}),
22+
endpoints: (build) => ({
23+
getTodos: build.query<Todos, string>({
24+
query: () => '/todos',
25+
}),
26+
}),
27+
})
28+
29+
const exampleQuerySelector = exampleApi.endpoints.getTodos.select('/')
30+
31+
const todosSelector = createSelector(
32+
[exampleQuerySelector],
33+
(queryState) => {
34+
return queryState?.data?.[0] ?? ({} as Todo)
35+
}
36+
)
37+
const firstTodoTitleSelector = createSelector(
38+
[todosSelector],
39+
(todo) => todo?.title
40+
)
41+
42+
const store = configureStore({
43+
reducer: {
44+
[exampleApi.reducerPath]: exampleApi.reducer,
45+
},
46+
})
47+
48+
const todoTitle = firstTodoTitleSelector(store.getState())
49+
50+
// This only compiles if we carried the types through
51+
const upperTitle = todoTitle.toUpperCase()
52+
expectExactType<string>(upperTitle)
53+
})
54+
})

0 commit comments

Comments
 (0)