Skip to content

Commit

Permalink
Merge pull request #1646 from reduxjs/expose-endpoint-types
Browse files Browse the repository at this point in the history
  • Loading branch information
markerikson authored Aug 16, 2022
2 parents b4e8d94 + 4862161 commit 22d0fbb
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 2 deletions.
14 changes: 12 additions & 2 deletions packages/toolkit/src/query/core/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,15 +320,25 @@ export interface ApiEndpointQuery<
Definition extends QueryDefinition<any, any, any, any, any>,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Definitions extends EndpointDefinitions
> {}
> {
/**
* All of these are `undefined` at runtime, purely to be used in TypeScript declarations!
*/
Types: NonNullable<Definition['Types']>
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export interface ApiEndpointMutation<
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Definition extends MutationDefinition<any, any, any, any, any>,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Definitions extends EndpointDefinitions
> {}
> {
/**
* All of these are `undefined` at runtime, purely to be used in TypeScript declarations!
*/
Types: NonNullable<Definition['Types']>
}

export type ListenerActions = {
/**
Expand Down
70 changes: 70 additions & 0 deletions packages/toolkit/src/query/endpointDefinitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,16 @@ interface EndpointDefinitionWithQueryFn<
structuralSharing?: boolean
}

export interface BaseEndpointTypes<
QueryArg,
BaseQuery extends BaseQueryFn,
ResultType
> {
QueryArg: QueryArg
BaseQuery: BaseQuery
ResultType: ResultType
}

export type BaseEndpointDefinition<
QueryArg,
BaseQuery extends BaseQueryFn,
Expand Down Expand Up @@ -221,6 +231,31 @@ export interface QueryApi<ReducerPath extends string, Context extends {}> {
context: Context
}

export interface QueryTypes<
QueryArg,
BaseQuery extends BaseQueryFn,
TagTypes extends string,
ResultType,
ReducerPath extends string = string
> extends BaseEndpointTypes<QueryArg, BaseQuery, ResultType> {
/**
* The endpoint definition type. To be used with some internal generic types.
* @example
* ```ts
* const useMyWrappedHook: UseQuery<typeof api.endpoints.query.Types.QueryDefinition> = ...
* ```
*/
QueryDefinition: QueryDefinition<
QueryArg,
BaseQuery,
TagTypes,
ResultType,
ReducerPath
>
TagTypes: TagTypes
ReducerPath: ReducerPath
}

export interface QueryExtraOptions<
TagTypes extends string,
ResultType,
Expand Down Expand Up @@ -303,6 +338,11 @@ export interface QueryExtraOptions<
currentCacheData: ResultType,
responseData: ResultType
): ResultType | void

/**
* All of these are `undefined` at runtime, purely to be used in TypeScript declarations!
*/
Types?: QueryTypes<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath>
}

export type QueryDefinition<
Expand All @@ -314,6 +354,31 @@ export type QueryDefinition<
> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType> &
QueryExtraOptions<TagTypes, ResultType, QueryArg, BaseQuery, ReducerPath>

export interface MutationTypes<
QueryArg,
BaseQuery extends BaseQueryFn,
TagTypes extends string,
ResultType,
ReducerPath extends string = string
> extends BaseEndpointTypes<QueryArg, BaseQuery, ResultType> {
/**
* The endpoint definition type. To be used with some internal generic types.
* @example
* ```ts
* const useMyWrappedHook: UseMutation<typeof api.endpoints.query.Types.MutationDefinition> = ...
* ```
*/
MutationDefinition: MutationDefinition<
QueryArg,
BaseQuery,
TagTypes,
ResultType,
ReducerPath
>
TagTypes: TagTypes
ReducerPath: ReducerPath
}

export interface MutationExtraOptions<
TagTypes extends string,
ResultType,
Expand Down Expand Up @@ -378,6 +443,11 @@ export interface MutationExtraOptions<
* Not to be used. A mutation should not provide tags to the cache.
*/
providesTags?: never

/**
* All of these are `undefined` at runtime, purely to be used in TypeScript declarations!
*/
Types?: MutationTypes<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath>
}

export type MutationDefinition<
Expand Down
21 changes: 21 additions & 0 deletions packages/toolkit/src/query/tests/buildHooks.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import * as React from 'react'
import type {
UseMutation,
UseQuery,
} from '@reduxjs/toolkit/dist/query/react/buildHooks'
import {
createApi,
fetchBaseQuery,
Expand Down Expand Up @@ -2363,3 +2367,20 @@ describe('skip behaviour', () => {
expect(subscriptionCount('getUser(1)')).toBe(0)
})
})

// type tests:
{
const ANY = {} as any

// UseQuery type can be used to recreate the hook type
const fakeQuery = ANY as UseQuery<
typeof api.endpoints.getUser.Types.QueryDefinition
>
expectExactType(fakeQuery)(api.endpoints.getUser.useQuery)

// UseMutation type can be used to recreate the hook type
const fakeMutation = ANY as UseMutation<
typeof api.endpoints.updateUser.Types.MutationDefinition
>
expectExactType(fakeMutation)(api.endpoints.updateUser.useMutation)
}

0 comments on commit 22d0fbb

Please sign in to comment.