Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: TypeScript Type Portability Issues #4467

Open
wants to merge 85 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
97e0b9f
Remove `esbuild` from root `package.json`'s `resolutions` field
aryaemami59 Jun 18, 2024
313bcd5
Add `esbuild` to `devDependencies` of `toolkit`
aryaemami59 Jun 18, 2024
e462868
Initial attempt at bundling type definitions
aryaemami59 Jun 18, 2024
682ef46
Add names to build artifacts
aryaemami59 Jun 18, 2024
557a22d
Add `satisfies `TsupOptions[]``
aryaemami59 Jun 18, 2024
1aa9d1f
Fix exports in `src/query/utils/index.ts` barrel file
aryaemami59 Jun 18, 2024
62808c0
Fix exports in `src/query/core/buildMiddleware/index.ts` barrel file
aryaemami59 Jun 18, 2024
35795ea
Fix exports in `src/query/core/index.ts` barrel file
aryaemami59 Jun 18, 2024
ef2139b
Remove relative `declare module`s
aryaemami59 Jun 18, 2024
bafcea8
Fix `build` command
aryaemami59 Jun 18, 2024
7e7c806
Bump `tsup` to version 8.1.0
aryaemami59 Jun 18, 2024
e490c7f
Bump `tsx` to version 4.15.6
aryaemami59 Jun 18, 2024
4fd11f0
Add a script to manually fix `unique symbol` exports
aryaemami59 Jun 18, 2024
08f2113
Export `CombinedSliceReducer`
aryaemami59 Jun 18, 2024
debb422
Convert `TS4023` related interfaces in `createSlice.ts` to types
aryaemami59 Jun 18, 2024
bc5744a
Convert `GetSelectorsOptions` to a `type` alias
aryaemami59 Jun 18, 2024
a3c254c
Rename `Id` to `Simplify` to prevent naming collision
aryaemami59 Jun 18, 2024
8c703e7
Convert `QueryHooks` to a `type` alias
aryaemami59 Jun 18, 2024
929c504
Convert `CaseReducerDefinition` to a `type` alias
aryaemami59 Jun 18, 2024
4340c7b
Export `UNINITIALIZED_VALUE`
aryaemami59 Jun 18, 2024
084fc0e
De-duplicate `type` imports
aryaemami59 Jun 18, 2024
a0baec3
Convert `PromiseWithKnownReason` to a `type` alias
aryaemami59 Jun 18, 2024
580a5e8
Convert `MutationHooks` to a `type` alias
aryaemami59 Jun 18, 2024
ea4382e
Export `StartQueryActionCreatorOptions` type
aryaemami59 Jun 18, 2024
df36b6f
Fix issue with renaming type imports
aryaemami59 Jun 18, 2024
2d63d53
De-duplicate `IgnorePaths` type
aryaemami59 Jun 18, 2024
b1004e9
Remove `Omit` from `tsHelpers.ts` to avoid collision with native `Omit`
aryaemami59 Jun 18, 2024
bf38160
Rename `TypedActionCreator` to `TypedActionCreatorWithMatchFunction`
aryaemami59 Jun 18, 2024
7f63c84
De-duplicate `GetState` type
aryaemami59 Jun 18, 2024
bb48347
Remove unused `_Keep` type in `createAsyncThunk.ts`
aryaemami59 Jun 18, 2024
db48a61
Rename `GetDispatch` to `GetDispatchType`
aryaemami59 Jun 19, 2024
fb3ba9c
Do not export `CacheLifecyclePromises`
aryaemami59 Jun 19, 2024
1302fcf
Do not export `QueryLifecyclePromises`
aryaemami59 Jun 19, 2024
02c9b02
Do not export `LifecycleApi`
aryaemami59 Jun 19, 2024
19750ce
Add `.js` extension to `uncheckedindexed` import path
aryaemami59 Jun 19, 2024
0ab7134
Patch `console-testing-library`
aryaemami59 Jun 19, 2024
8513c89
Add `type` imports in `sorted_state_adapter.test.ts`
aryaemami59 Jun 19, 2024
f000e00
Run type tests with `"moduleResolution": "Bundler"` during CI
aryaemami59 Jun 19, 2024
5bd78f8
Add `@examples-type-portability/bundler` to workspaces
aryaemami59 Jun 19, 2024
1b47971
Update CI to test type portability with `moduleResolution Bundler`
aryaemami59 Jun 19, 2024
51e9cd5
Undo renaming of `Id` to `Simplify`
aryaemami59 Jun 19, 2024
c92ac90
Merge branch 'master' of https://github.com/reduxjs/redux-toolkit int…
aryaemami59 Jun 21, 2024
d8dcd01
Bump `tsx` to version 4.15.7
aryaemami59 Jun 21, 2024
ae87236
Update lockfile
aryaemami59 Jun 21, 2024
dc00686
Fix CI
aryaemami59 Jun 21, 2024
d47bd79
Merge branch 'master' of https://github.com/reduxjs/redux-toolkit int…
aryaemami59 Jun 28, 2024
a61bff5
Bump `tsx` to version 4.16.0
aryaemami59 Jun 29, 2024
93cbe55
Merge branch 'master' of https://github.com/reduxjs/redux-toolkit int…
aryaemami59 Jul 9, 2024
f6a49ef
Bump `tsx` to version 4.16.2
aryaemami59 Jul 9, 2024
e5aaa53
Update lockfile
aryaemami59 Jul 9, 2024
9d4b726
Undo export of `neverResolvedError`
aryaemami59 Jul 9, 2024
160328c
Add TypeScript version matrix for `@examples-type-portability/bundler`
aryaemami59 Jul 9, 2024
5b450cd
Export `BaseEndpointDefinition`
aryaemami59 Jul 9, 2024
e8a56ef
Fix job names in CI
aryaemami59 Jul 9, 2024
d3fe0ba
Bump TypeScript to version 5.5 for `@examples-type-portability/bundler`
aryaemami59 Jul 9, 2024
2c23f0d
Fix TS matrix
aryaemami59 Jul 9, 2024
78a9d60
Convert `React` import to wildcard import
aryaemami59 Jul 9, 2024
39e3df8
Run type tests with `"moduleResolution": "Node10"` in CI
aryaemami59 Jul 9, 2024
8ab3377
Run type tests with `moduleResolution Node10` and `type module` in CI
aryaemami59 Jul 9, 2024
beb818c
Add `next` to TS versions in matrix
aryaemami59 Jul 9, 2024
7008dfb
Enable `preserveSymLinks` when running `tsc` with `Node10`
aryaemami59 Jul 9, 2024
2cef306
Convert `EndpointDefinitionWithQueryFn` to a `type` alias
aryaemami59 Jul 9, 2024
f0bcced
Convert `EndpointDefinitionWithQuery` to a `type` alias
aryaemami59 Jul 9, 2024
c018271
Merge `MutationExtraOptions` interface into a single declaration
aryaemami59 Jul 9, 2024
2b60052
Merge `QueryExtraOptions` interface into a single declaration
aryaemami59 Jul 9, 2024
de845ec
Merge `ApiEndpointQuery` interface into a single declaration
aryaemami59 Jul 9, 2024
9cbb08a
Merge `ApiEndpointMutation` interface into a single declaration
aryaemami59 Jul 9, 2024
25588dd
Merge `ApiModules` interface into a single declaration
aryaemami59 Jul 9, 2024
0b8e8e5
Move `@examples-type-portability/bundler` to `type-portability/bundler`
aryaemami59 Jul 9, 2024
ba32b7b
Add `@examples-type-portability/nodenext-cjs`
aryaemami59 Jul 9, 2024
b0bfe79
Run type portability tests on `@examples-type-portability/nodenext-cjs`
aryaemami59 Jul 9, 2024
59b451b
Remove import attributes as they are not compatible with TypeScript v5.2
aryaemami59 Jul 9, 2024
fc001dd
Add `@examples-type-portability/nodenext-esm`
aryaemami59 Jul 9, 2024
d32d35d
Run type portability tests on `@examples-type-portability/nodenext-esm`
aryaemami59 Jul 9, 2024
b2d1a8c
Use matrices for type portability examples in CI
aryaemami59 Jul 9, 2024
70286c2
Rename `examples` to `example`
aryaemami59 Jul 9, 2024
2e503cc
Skip `Node10` ESM test for `@examples-type-portability/nodenext-cjs`
aryaemami59 Jul 9, 2024
5b5c212
Run `Node10` tests with `preserveSymLinks` enabled
aryaemami59 Jul 9, 2024
e02d94f
Disable `verbatimModuleSyntax` for `Node10`
aryaemami59 Jul 9, 2024
fb85f03
Bump dependencies for `@examples-type-portability/nodenext-esm`
aryaemami59 Jul 9, 2024
0642169
Bump dependencies for `@examples-type-portability/bundler`
aryaemami59 Jul 9, 2024
51154ab
Fix description of `@examples-type-portability/bundler`
aryaemami59 Jul 9, 2024
7116382
Fix `tsconfig.json` of `@examples-type-portability/bundler`
aryaemami59 Jul 9, 2024
da50c57
Fix `package.json` of `@examples-type-portability/bundler`
aryaemami59 Jul 9, 2024
06a30ee
Update lockfile
aryaemami59 Jul 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Remove relative declare modules
- We also convert some of the problematic types from an `interface` to a `type` alias.
  • Loading branch information
aryaemami59 committed Jun 18, 2024
commit ef2139b230c5a18976e0b241c3de0fa0390208ab
353 changes: 346 additions & 7 deletions packages/toolkit/src/query/apiTypes.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,47 @@
import type {
EndpointDefinitions,
ActionCreatorWithPayload,
Middleware,
Reducer,
ThunkAction,
ThunkDispatch,
UnknownAction,
} from '@reduxjs/toolkit'
import type { BaseQueryFn } from './baseQueryTypes'
import type {
ApiEndpointMutation,
ApiEndpointQuery,
CombinedState,
CoreModule,
coreModuleName,
InternalActions,
MutationActionCreatorResult,
MutationKeys,
PatchQueryDataThunk,
PrefetchOptions,
QueryActionCreatorResult,
QueryKeys,
RootState,
SliceActions,
ThunkWithReturnValue,
UpdateQueryDataThunk,
UpsertQueryDataThunk,
} from './core'
import type { CreateApiOptions } from './createApi'
import type {
EndpointBuilder,
EndpointDefinition,
EndpointDefinitions,
MutationDefinition,
QueryArgFrom,
QueryDefinition,
TagDescription,
UpdateDefinitions,
} from './endpointDefinitions'
import type {
UnionToIntersection,
NoInfer,
UnionToIntersection,
WithRequiredProp,
} from './tsHelpers'
import type { CoreModule } from './core/module'
import type { CreateApiOptions } from './createApi'
import type { BaseQueryFn } from './baseQueryTypes'
import type { CombinedState } from './core/apiState'
import type { UnknownAction } from '@reduxjs/toolkit'

export interface ApiModules<
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -26,6 +54,317 @@ export interface ApiModules<
TagTypes extends string,
> {}

export interface ApiModules<
// eslint-disable-next-line @typescript-eslint/no-unused-vars
BaseQuery extends BaseQueryFn,
Definitions extends EndpointDefinitions,
ReducerPath extends string,
TagTypes extends string,
> {
[coreModuleName]: {
/**
* This api's reducer should be mounted at `store[api.reducerPath]`.
*
* @example
* ```ts
* configureStore({
* reducer: {
* [api.reducerPath]: api.reducer,
* },
* middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware),
* })
* ```
*/
reducerPath: ReducerPath
/**
* Internal actions not part of the public API. Note: These are subject to change at any given time.
*/
internalActions: InternalActions
/**
* A standard redux reducer that enables core functionality. Make sure it's included in your store.
*
* @example
* ```ts
* configureStore({
* reducer: {
* [api.reducerPath]: api.reducer,
* },
* middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware),
* })
* ```
*/
reducer: Reducer<
CombinedState<Definitions, TagTypes, ReducerPath>,
UnknownAction
>
/**
* This is a standard redux middleware and is responsible for things like polling, garbage collection and a handful of other things. Make sure it's included in your store.
*
* @example
* ```ts
* configureStore({
* reducer: {
* [api.reducerPath]: api.reducer,
* },
* middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware),
* })
* ```
*/
middleware: Middleware<
{},
RootState<Definitions, string, ReducerPath>,
ThunkDispatch<any, any, UnknownAction>
>
/**
* A collection of utility thunks for various situations.
*/
util: {
/**
* A thunk that (if dispatched) will return a specific running query, identified
* by `endpointName` and `args`.
* If that query is not running, dispatching the thunk will result in `undefined`.
*
* Can be used to await a specific query triggered in any way,
* including via hook calls or manually dispatching `initiate` actions.
*
* See https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details.
*/
getRunningQueryThunk<EndpointName extends QueryKeys<Definitions>>(
endpointName: EndpointName,
args: QueryArgFrom<Definitions[EndpointName]>,
): ThunkWithReturnValue<
| QueryActionCreatorResult<
Definitions[EndpointName] & { type: 'query' }
>
| undefined
>

/**
* A thunk that (if dispatched) will return a specific running mutation, identified
* by `endpointName` and `fixedCacheKey` or `requestId`.
* If that mutation is not running, dispatching the thunk will result in `undefined`.
*
* Can be used to await a specific mutation triggered in any way,
* including via hook trigger functions or manually dispatching `initiate` actions.
*
* See https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details.
*/
getRunningMutationThunk<EndpointName extends MutationKeys<Definitions>>(
endpointName: EndpointName,
fixedCacheKeyOrRequestId: string,
): ThunkWithReturnValue<
| MutationActionCreatorResult<
Definitions[EndpointName] & { type: 'mutation' }
>
| undefined
>

/**
* A thunk that (if dispatched) will return all running queries.
*
* Useful for SSR scenarios to await all running queries triggered in any way,
* including via hook calls or manually dispatching `initiate` actions.
*
* See https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details.
*/
getRunningQueriesThunk(): ThunkWithReturnValue<
Array<QueryActionCreatorResult<any>>
>

/**
* A thunk that (if dispatched) will return all running mutations.
*
* Useful for SSR scenarios to await all running mutations triggered in any way,
* including via hook calls or manually dispatching `initiate` actions.
*
* See https://redux-toolkit.js.org/rtk-query/usage/server-side-rendering for details.
*/
getRunningMutationsThunk(): ThunkWithReturnValue<
Array<MutationActionCreatorResult<any>>
>

/**
* A Redux thunk that can be used to manually trigger pre-fetching of data.
*
* The thunk accepts three arguments: the name of the endpoint we are updating (such as `'getPost'`), the appropriate query arg values to construct the desired cache key, and a set of options used to determine if the data actually should be re-fetched based on cache staleness.
*
* React Hooks users will most likely never need to use this directly, as the `usePrefetch` hook will dispatch this thunk internally as needed when you call the prefetching function supplied by the hook.
*
* @example
*
* ```ts no-transpile
* dispatch(api.util.prefetch('getPosts', undefined, { force: true }))
* ```
*/
prefetch<EndpointName extends QueryKeys<Definitions>>(
endpointName: EndpointName,
arg: QueryArgFrom<Definitions[EndpointName]>,
options: PrefetchOptions,
): ThunkAction<void, any, any, UnknownAction>
/**
* A Redux thunk action creator that, when dispatched, creates and applies a set of JSON diff/patch objects to the current state. This immediately updates the Redux state with those changes.
*
* The thunk action creator accepts three arguments: the name of the endpoint we are updating (such as `'getPost'`), the appropriate query arg values to construct the desired cache key, and an `updateRecipe` callback function. The callback receives an Immer-wrapped `draft` of the current state, and may modify the draft to match the expected results after the mutation completes successfully.
*
* The thunk executes _synchronously_, and returns an object containing `{patches: Patch[], inversePatches: Patch[], undo: () => void}`. The `patches` and `inversePatches` are generated using Immer's [`produceWithPatches` method](https://immerjs.github.io/immer/patches).
*
* This is typically used as the first step in implementing optimistic updates. The generated `inversePatches` can be used to revert the updates by calling `dispatch(patchQueryData(endpointName, args, inversePatches))`. Alternatively, the `undo` method can be called directly to achieve the same effect.
*
* Note that the first two arguments (`endpointName` and `args`) are used to determine which existing cache entry to update. If no existing cache entry is found, the `updateRecipe` callback will not run.
*
* @example
*
* ```ts
* const patchCollection = dispatch(
* api.util.updateQueryData('getPosts', undefined, (draftPosts) => {
* draftPosts.push({ id: 1, name: 'Teddy' })
* })
* )
* ```
*/
updateQueryData: UpdateQueryDataThunk<
Definitions,
RootState<Definitions, string, ReducerPath>
>

/**
* A Redux thunk action creator that, when dispatched, acts as an artificial API request to upsert a value into the cache.
*
* The thunk action creator accepts three arguments: the name of the endpoint we are updating (such as `'getPost'`), the appropriate query arg values to construct the desired cache key, and the data to upsert.
*
* If no cache entry for that cache key exists, a cache entry will be created and the data added. If a cache entry already exists, this will _overwrite_ the existing cache entry data.
*
* The thunk executes _asynchronously_, and returns a promise that resolves when the store has been updated.
*
* If dispatched while an actual request is in progress, both the upsert and request will be handled as soon as they resolve, resulting in a "last result wins" update behavior.
*
* @example
*
* ```ts
* await dispatch(
* api.util.upsertQueryData('getPost', {id: 1}, {id: 1, text: "Hello!"})
* )
* ```
*/
upsertQueryData: UpsertQueryDataThunk<
Definitions,
RootState<Definitions, string, ReducerPath>
>
/**
* A Redux thunk that applies a JSON diff/patch array to the cached data for a given query result. This immediately updates the Redux state with those changes.
*
* The thunk accepts three arguments: the name of the endpoint we are updating (such as `'getPost'`), the appropriate query arg values to construct the desired cache key, and a JSON diff/patch array as produced by Immer's `produceWithPatches`.
*
* This is typically used as the second step in implementing optimistic updates. If a request fails, the optimistically-applied changes can be reverted by dispatching `patchQueryData` with the `inversePatches` that were generated by `updateQueryData` earlier.
*
* In cases where it is desired to simply revert the previous changes, it may be preferable to call the `undo` method returned from dispatching `updateQueryData` instead.
*
* @example
* ```ts
* const patchCollection = dispatch(
* api.util.updateQueryData('getPosts', undefined, (draftPosts) => {
* draftPosts.push({ id: 1, name: 'Teddy' })
* })
* )
*
* // later
* dispatch(
* api.util.patchQueryData('getPosts', undefined, patchCollection.inversePatches)
* )
*
* // or
* patchCollection.undo()
* ```
*/
patchQueryData: PatchQueryDataThunk<
Definitions,
RootState<Definitions, string, ReducerPath>
>

/**
* A Redux action creator that can be dispatched to manually reset the api state completely. This will immediately remove all existing cache entries, and all queries will be considered 'uninitialized'.
*
* @example
*
* ```ts
* dispatch(api.util.resetApiState())
* ```
*/
resetApiState: SliceActions['resetApiState']
/**
* A Redux action creator that can be used to manually invalidate cache tags for [automated re-fetching](../../usage/automated-refetching.mdx).
*
* The action creator accepts one argument: the cache tags to be invalidated. It returns an action with those tags as a payload, and the corresponding `invalidateTags` action type for the api.
*
* Dispatching the result of this action creator will [invalidate](../../usage/automated-refetching.mdx#invalidating-cache-data) the given tags, causing queries to automatically re-fetch if they are subscribed to cache data that [provides](../../usage/automated-refetching.mdx#providing-cache-data) the corresponding tags.
*
* The array of tags provided to the action creator should be in one of the following formats, where `TagType` is equal to a string provided to the [`tagTypes`](../createApi.mdx#tagtypes) property of the api:
*
* - `[TagType]`
* - `[{ type: TagType }]`
* - `[{ type: TagType, id: number | string }]`
*
* @example
*
* ```ts
* dispatch(api.util.invalidateTags(['Post']))
* dispatch(api.util.invalidateTags([{ type: 'Post', id: 1 }]))
* dispatch(
* api.util.invalidateTags([
* { type: 'Post', id: 1 },
* { type: 'Post', id: 'LIST' },
* ])
* )
* ```
*/
invalidateTags: ActionCreatorWithPayload<
Array<TagDescription<TagTypes>>,
string
>

/**
* A function to select all `{ endpointName, originalArgs, queryCacheKey }` combinations that would be invalidated by a specific set of tags.
*
* Can be used for mutations that want to do optimistic updates instead of invalidating a set of tags, but don't know exactly what they need to update.
*/
selectInvalidatedBy: (
state: RootState<Definitions, string, ReducerPath>,
tags: ReadonlyArray<TagDescription<TagTypes>>,
) => Array<{
endpointName: string
originalArgs: any
queryCacheKey: string
}>

/**
* A function to select all arguments currently cached for a given endpoint.
*
* Can be used for mutations that want to do optimistic updates instead of invalidating a set of tags, but don't know exactly what they need to update.
*/
selectCachedArgsForQuery: <QueryName extends QueryKeys<Definitions>>(
state: RootState<Definitions, string, ReducerPath>,
queryName: QueryName,
) => Array<QueryArgFrom<Definitions[QueryName]>>
}
/**
* Endpoints based on the input endpoints provided to `createApi`, containing `select` and `action matchers`.
*/
endpoints: {
[K in keyof Definitions]: Definitions[K] extends QueryDefinition<
any,
any,
any,
any,
any
>
? ApiEndpointQuery<Definitions[K], Definitions>
: Definitions[K] extends MutationDefinition<any, any, any, any, any>
? ApiEndpointMutation<Definitions[K], Definitions>
: never
}
}
}

export type ModuleName = keyof ApiModules<any, any, any, any>

export type Module<Name extends ModuleName> = {
Expand Down
Loading