Repository: reduxjs/redux-toolkit
Pull request #1018 (2021-04-25 08:56:31)

Docs - RTKQ - Flesh out content on hooks api page
Fleshes out missing content for the RTK Query hooks api page. 

- Adds pseudo type signatures for each hook
- Adds brief descriptions of hook parameters/return values
- Adds brief hook descriptions
- Adds 'feature' points for each hook
- Adds a 'feature comparison' table for a quick eyeball comparison of what each hook does

Some descriptions do feel a bit brief, but it's more than nothing

codesandbox[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/reduxjs/redux-toolkit/pr/1018/builds/123415) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit a546773e30b20a70ec17e79b06a17cf35cf6c966:

|Sandbox| Source |
|--|--|
|[Vanilla](https://codesandbox.io/s/vanilla-eine9)| Configuration |
|[Vanilla Typescript](https://codesandbox.io/s/vanilla-typescript-bhbwq)| Configuration |
|[rsk-github-issues-example](https://codesandbox.io/s/rsk-github-issues-example-p1xs2)| Configuration |

netlify[bot]: Deploy preview for *redux-starter-kit-docs* ready!

Built with commit a546773e30b20a70ec17e79b06a17cf35cf6c966

https://deploy-preview-1018--redux-starter-kit-docs.netlify.app
Shrugsy: @markerikson, @phryneas, @msutkowski; If anyone has some good descriptions for the missing/brief ones, please feel free to fill them in or post them here.

In particular, I wasn't confident in describing these accurately:
- `useQueryState` (description)
- `useQuerySubscription` (description)
- `useLazyQuerySubscription` (options + description)
Shrugsy: > @markerikson, @phryneas, @msutkowski; If anyone has some good descriptions for the missing/brief ones, please feel free to fill them in or post them here.
> 
> In particular, I wasn't confident in describing these accurately:
> ~- `useQueryState` (description)~
> ~- `useQuerySubscription` (description)~
> 
> * `useLazyQuerySubscription` (options + description)

I've added short descriptions for `useQueryState` and `useQuerySubscription`.

However I'm not sure exactly what `useLazyQuerySubscription` does.

If a `QuerySubscription` hook is concerned with the automatic fetching lifecycle, and the `Lazy` hook is concerned with opting out of the automatic fetching lifecycle to perform fetches manually, what does `useLazyQuerySubscription` do?

I'm sure I'm just missing a key understanding for one or both of the hooks
markerikson: My vague understanding just based on the chats and PRs is that the pieces are:

- "state": reads the data and re-renders
- "subscription": actually triggers a fetch of the data, and does so automatically
- "lazy": triggers a fetch of the data, but only when you tell it to manually
- "query": wraps matching "state" + "subscription" hooks

So, I _assume_ that `useLazyQuerySubscription` is "just a fetch of the data without reading it and re-rendering, but only triggers when you tell it to".
Shrugsy: > So, I assume that useLazyQuerySubscription is "just a fetch of the data without reading it and re-rendering, but only triggers when you tell it to".

Ah that wording made it click for me, thanks heaps. I was too tied up trying to correlate `subscription` with 'automatic fetching'
markerikson: Y'know, when you put it that way, it's almost like "subscription" is the wrong word to use for those hooks.  What would be better? "Fetch"? "Request"?  For that matter, once you trigger a lazy subscription, does all the normal timing/polling/whatever stuff kick in from there on out?  If so, maybe "subscription" is fine.
Shrugsy: > For that matter, once you trigger a lazy subscription, does all the normal timing/polling/whatever stuff kick in from there on out? If so, maybe "subscription" is fine.

Yep, it's exactly like that. I think `subscription` is fitting. Getting all of that info together, `LazyQuerySubscription` definitely makes sense
phryneas: @markerikson @Shrugsy  "subscription" is exactly that, but on another level than you think: the *component* subscribes to a *cache value in the store* to keep it from getting collected.

So yes, `useQuerySubscription` fetches data etc, but a normal `dispatch(initiate)` would do that too - but then it keeps it in the store and "unsubscribes" on unmount, so it's more about the component lifecycle synchronisation thing.
Same for `useLazyQuery`.
Shrugsy: Thanks @phryneas, that's a good clarification. I think the updated hook descriptions should be pretty accurate now

Patch:
diff --git a/.eslintrc.js b/.eslintrc.js
index a65604a4..fde5ac99 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -2,7 +2,7 @@ module.exports = {
   extends: [
     'react-app',
     'prettier/@typescript-eslint',
-    'plugin:prettier/recommended'
+    'plugin:prettier/recommended',
   ],
   parser: '@typescript-eslint/parser',
   rules: {
@@ -11,6 +11,19 @@ module.exports = {
     'no-unused-vars': 'off',
     '@typescript-eslint/no-unused-vars': 'off',
     // Silence some bizarre "rule not found" TSLint error
-    '@typescript-eslint/no-angle-bracket-type-assertion': 'off'
-  }
+    '@typescript-eslint/no-angle-bracket-type-assertion': 'off',
+    'no-redeclare': 'off',
+    '@typescript-eslint/no-redeclare': ['error'],
+    'no-use-before-define': 'off',
+    '@typescript-eslint/no-use-before-define': ['error', { functions: false }],
+  },
+  overrides: [
+    {
+      files: ['src/tests/*.ts', 'src/**/tests/*.ts', 'src/**/tests/*.tsx'],
+      rules: {
+        '@typescript-eslint/no-unused-expressions': 'off',
+        'no-lone-blocks': 'off',
+      },
+    },
+  ],
 }
diff --git a/docs/api/rtk-query/created-api/hooks.md b/docs/api/rtk-query/created-api/hooks.md
index 1cd87557..184ad6b4 100644
--- a/docs/api/rtk-query/created-api/hooks.md
+++ b/docs/api/rtk-query/created-api/hooks.md
@@ -14,10 +14,10 @@ The core RTK Query `createApi` method is UI-agnostic, in the same way that the R
 However, RTK Query also provides the ability to auto-generate React hooks for each of your endpoints. Since this specifically depends on React itself, RTK Query provides an alternate entry point that exposes a customized version of `createApi` that includes that functionality:
 
 ```js
-import { createApi } from 'reduxjs/toolkit/query/react'
+import { createApi } from '@reduxjs/toolkit/query/react'
 ```
 
-If you have used the React-specific version of `createApi`, the generated `Api` slice structure will also contain a set of React hooks. These endpoint hooks are available as `api.endpoints[endpointName].useQuery` or `api.endpoints[endpointName].useMutation`, matching how you defined that endpoint.
+If you have used the React-specific version of `createApi`, the generated `Api` slice structure will also contain a set of React hooks. The primary endpoint hooks are available as `api.endpoints[endpointName].useQuery` or `api.endpoints[endpointName].useMutation`, matching how you defined that endpoint.
 
 The same hooks are also added to the `Api` object itself, and given auto-generated names based on the endpoint name and query/mutation type.
 
@@ -26,16 +26,170 @@ For example, if you had endpoints for `getPosts` and `updatePost`, these options
 ```ts title="Generated React Hook names"
 // Hooks attached to the endpoint definition
 const { data } = api.endpoints.getPosts.useQuery()
-const { data } = api.endpoints.updatePost.useMutation()
+const [updatePost, { data }] = api.endpoints.updatePost.useMutation()
 
 // Same hooks, but given unique names and attached to the API slice object
 const { data } = api.useGetPostsQuery()
-const [updatePost] = api.useUpdatePostMutation()
+const [updatePost, { data }] = api.useUpdatePostMutation()
 ```
 
 The general format is `use(Endpointname)(Query|Mutation)` - `use` is prefixed, the first letter of your endpoint name is capitalized, then `Query` or `Mutation` is appended depending on the type.
 
-The React-specific version of `createApi` also generates a `usePrefetch` hook, attached to the `Api` object, which can be used to initiate fetching data ahead of time.
+The full list of hooks generated in the React-specific version of `createApi` is as follows:
+
+- [`useQuery`](#usequery) (endpoint-specific)
+- [`useMutation`](#usemutation) (endpoint-specific)
+- [`useQueryState`](#usequerystate) (endpoint-specific)
+- [`useQuerySubscription`](#usequerysubscription) (endpoint-specific)
+- [`useLazyQuery`](#uselazyquery) (endpoint-specific)
+- [`useLazyQuerySubscription`](#uselazyquerysubscription) (endpoint-specific)
+- [`usePrefetch`](#useprefetch) (endpoint-agnostic)
+
+For the example above, the full set of generated hooks for the api would be like so:
+
+```ts title="Generated React Hooks"
+/* Hooks attached to the `getPosts` query endpoint definition */
+const { data } = api.endpoints.getPosts.useQuery(arg, options)
+const post = api.endpoints.getPosts.useQueryState(arg, options)
+const { refetch } = api.endpoints.getPosts.useQuerySubscription(arg, options)
+const [getPosts, { data }, { lastArg }] = api.endpoints.getPosts.useLazyQuery(
+  options
+)
+const [getPosts, lastArg] = api.endpoints.getPosts.useLazyQuerySubscription(
+  options
+)
+
+/* Hooks attached to the `updatePost` mutation endpoint definition */
+const [updatePost, { data }] = api.endpoints.updatePost.useMutation(options)
+
+/* Hooks attached to the `Api` object */
+// same as api.endpoints.getPosts.useQuery
+const { data } = api.useGetPostsQuery(arg, options)
+// same as api.endpoints.getPosts.useLazyQuery
+const [getPosts, { data }, { lastArg }] = api.useLazyGetPostsQuery(options)
+// same as api.endpoints.updatePost.useMutation
+const [updatePost, { data }] = api.useUpdatePostMutation(options)
+const fetchData = api.usePrefetch(endpointName, options)
+```
+
+### Feature Comparison
+
+The provided hooks have a degree of feature overlap in order to provide options optimized for a given situation. The table below provides a comparison of the core features for each hook.
+
+<table style={{'overflow-y': 'hidden'}}>
+  <thead>
+    <tr style={{height: '250px', border: 'none'}}>
+      <th style={{width: '300px'}}>Feature</th>
+      <th style={{'white-space': 'nowrap', border: 'none'}}>
+        <div style={{transform: 'translate(0px, 51px) rotate(315deg)', width: '20px'}}>
+          <a href="#usequery">useQuery</a>
+        </div>
+      </th>
+      <th style={{'white-space': 'nowrap', border: 'none'}}>
+        <div style={{transform: 'translate(0px, 51px) rotate(315deg)', width: '20px'}}>
+          <a href="#usemutation">useMutation</a>
+        </div>
+      </th>
+      <th style={{'white-space': 'nowrap', border: 'none'}}>
+        <div style={{transform: 'translate(0px, 51px) rotate(315deg)', width: '20px'}}>
+          <a href="#usequerystate">useQueryState</a>
+        </div>
+      </th>
+      <th style={{'white-space': 'nowrap', border: 'none'}}>
+        <div style={{transform: 'translate(0px, 51px) rotate(315deg)', width: '20px'}}>
+          <a href="#usequerysubscription">useQuerySubscription</a>
+        </div>
+      </th>
+      <th style={{'white-space': 'nowrap', border: 'none'}}>
+        <div style={{transform: 'translate(0px, 51px) rotate(315deg)', width: '20px'}}>
+          <a href="#uselazyquery">useLazyQuery</a>
+        </div>
+      </th>
+      <th style={{'white-space': 'nowrap', border: 'none'}}>
+        <div style={{transform: 'translate(0px, 51px) rotate(315deg)', width: '20px'}}>
+          <a href="#uselazyquerysubscription">useLazyQuerySubscription</a>
+        </div>
+      </th>
+      <th style={{'white-space': 'nowrap', border: 'none'}}>
+        <div style={{transform: 'translate(0px, 51px) rotate(315deg)', width: '20px'}}>
+          <a href="#useprefetch">usePrefetch</a>
+        </div>
+      </th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td style={{width: '330px'}}>Automatically triggers query requests</td>
+      <td>✔️</td>
+      <td></td>
+      <td></td>
+      <td>✔️</td>
+      <td></td>
+      <td></td>
+      <td></td>
+    </tr>
+    <tr>
+      <td style={{width: '330px'}}>Allows manually triggering query requests</td>
+      <td>✔️</td>
+      <td></td>
+      <td></td>
+      <td>✔️</td>
+      <td>✔️</td>
+      <td>✔️</td>
+      <td>✔️</td>
+    </tr>
+    <tr>
+      <td style={{width: '330px'}}>Allows manually triggering mutation requests</td>
+      <td></td>
+      <td>✔️</td>
+      <td></td>
+      <td></td>
+      <td></td>
+      <td></td>
+      <td></td>
+    </tr>
+    <tr>
+      <td style={{width: '330px'}}>Subscribes a component to keep cached data in the store</td>
+      <td>✔️</td>
+      <td>✔️</td>
+      <td></td>
+      <td>✔️</td>
+      <td>✔️</td>
+      <td>✔️</td>
+      <td></td>
+    </tr>
+    <tr>
+      <td style={{width: '330px'}}>Returns request status and cached data from the store</td>
+      <td>✔️</td>
+      <td>✔️</td>
+      <td>✔️</td>
+      <td></td>
+      <td>✔️</td>
+      <td></td>
+      <td></td>
+    </tr>
+    <tr>
+      <td style={{width: '330px'}}>Re-renders as request status and data become available</td>
+      <td>✔️</td>
+      <td>✔️</td>
+      <td>✔️</td>
+      <td></td>
+      <td>✔️</td>
+      <td></td>
+      <td></td>
+    </tr>
+    <tr>
+      <td style={{width: '330px'}}>Accepts polling/re-fetching options to trigger automatic re-fetches</td>
+      <td>✔️</td>
+      <td></td>
+      <td></td>
+      <td>✔️</td>
+      <td>✔️</td>
+      <td>✔️</td>
+      <td></td>
+    </tr>
+  </tbody>
+</table>
 
 ## `useQuery`
 
@@ -55,7 +209,6 @@ type UseQueryOptions = {
 
 type UseQueryResult<T> = {
   // Base query state
-  status: 'uninitialized' | 'pending' | 'fulfilled' | 'rejected' // @deprecated - A string describing the query state
   originalArgs?: unknown // Arguments passed to the query
   data?: T // Returned result if present
   error?: unknown // Error result if present
@@ -78,56 +231,54 @@ type UseQueryResult<T> = {
   - `arg`: The query argument to be used in constructing the query itself, and as a cache key for the query
   - `options`: A set of options that control the fetching behavior of the hook
 - **Returns**
-  - A query result object containing the current loading state, the actual data or error returned from the API call, metadata about the request, and a function to `refetch` the data
+  - A query result object containing the current loading state, the actual data or error returned from the API call, metadata about the request, and a function to `refetch` the data. Can be customized with `selectFromResult`
 
 #### Description
 
-A React hook that triggers fetches of data from an endpoint, and subscribes the component to read the request status and cached data from the Redux store. The component will re-render as the loading status changes and the data becomes available.
-
-The query arg is used as a cache key. Changing the query arg will tell the hook to re-fetch the data if it does not exist in the cache already, and the hook will return the data for that query arg once it's available.
+[summary](docblock://query/react/buildHooks.ts?token=UseQuery)
 
 ## `useMutation`
 
 #### Signature
 
 ```ts
-type UseMutation<Definition> = (
-  UseMutationStateOptions<Definition>
-) => [UseMutationTrigger<Definition>, UseMutationResult<Definition> | SelectedUseMutationResult];
+type UseMutation = (
+  options?: UseMutationStateOptions
+) => [UseMutationTrigger, UseMutationResult | SelectedUseMutationResult]
 
-type UseMutationStateOptions<Definition> = {
+type UseMutationStateOptions = {
   // A method to determine the contents of `UseMutationResult`
   selectFromResult?: (state, defaultMutationStateSelector) => SelectedUseMutationResult extends Record<string, any>
 }
 
-type UseMutationTrigger<Definition> = (
-  arg: ArgTypeFrom<Definition>
-) => Promise<{ data: ResultTypeFrom<Definition> } | { error: BaseQueryError | SerializedError }> & {
-  requestId: string; // A string generated by RTK Query
-  abort: () => void; // A method to cancel the mutation promise
-  unwrap: () => Promise<ResultTypeFrom<Definition>>; // A method to unwrap the mutation call and provide the raw response/error
-  unsubscribe: () => void; // A method to manually unsubscribe from the mutation call
-};
-
-type UseMutationResult<Definition> = {
-  data?: ResultTypeFrom<Definition>; // Returned result if present
-  endpointName?: string; // The name of the given endpoint for the mutation
-  error?: any; // Error result if present
-  fulfilledTimestamp?: number; // Timestamp for when the mutation was completed
-  isError: boolean; // Mutation is currently in an "error" state
-  isLoading: boolean; // Mutation has been fired and is awaiting a response
-  isSuccess: boolean; // Mutation has data from a successful call
-  isUninitialized: boolean; // Mutation has not been fired yet
-  originalArgs?: ArgTypeFrom<Definition>; // Arguments passed to the latest mutation call
-  startedTimeStamp?: number; // Timestamp for when the latest mutation was initiated
-};
+type UseMutationTrigger<T> = (
+  arg: any
+) => Promise<{ data: T } | { error: BaseQueryError | SerializedError }> & {
+  requestId: string // A string generated by RTK Query
+  abort: () => void // A method to cancel the mutation promise
+  unwrap: () => Promise<T> // A method to unwrap the mutation call and provide the raw response/error
+  unsubscribe: () => void // A method to manually unsubscribe from the mutation call
+}
+
+type UseMutationResult<T> = {
+  data?: T // Returned result if present
+  endpointName?: string // The name of the given endpoint for the mutation
+  error?: unknown // Error result if present
+  fulfilledTimestamp?: number // Timestamp for when the mutation was completed
+  isError: boolean // Mutation is currently in an "error" state
+  isLoading: boolean // Mutation has been fired and is awaiting a response
+  isSuccess: boolean // Mutation has data from a successful call
+  isUninitialized: boolean // Mutation has not been fired yet
+  originalArgs?: unknown // Arguments passed to the latest mutation call
+  startedTimeStamp?: number // Timestamp for when the latest mutation was initiated
+}
 ```
 
 :::tip
 
-The generated `UseMutation` hook will cause a component to re-render by default after the trigger callback is fired as it affects the properties of the result. If you want to call the trigger but don't care about subscribing to the result with the hook, you can use the `selectFromResult` option to limit the properties that the hook cares about.
+The generated `UseMutation` hook will cause a component to re-render by default after the trigger callback is fired, as it affects the properties of the result. If you want to call the trigger but don't care about subscribing to the result with the hook, you can use the `selectFromResult` option to limit the properties that the hook cares about.
 
-Passing a completely empty object will prevent the hook from causing a re-render at all, e.g.
+Returning a completely empty object will mean that any individual mutation call will cause only one re-render at most, e.g.
 
 ```ts
 selectFromResult: () => ({})
@@ -135,30 +286,226 @@ selectFromResult: () => ({})
 
 :::
 
-- **Returns**: a tuple containing:
-  - `trigger`: a function that triggers an update to the data based on the provided argument. The trigger function returns a promise with the properties shown above that may be used to handle the behaviour of the promise.
-  - `mutationState`: a query status object containing the current loading state and metadata about the request
+- **Parameters**
+
+  - `options`: A set of options that control the subscription behavior of the hook
+
+- **Returns**: A tuple containing:
+  - `trigger`: A function that triggers an update to the data based on the provided argument. The trigger function returns a promise with the properties shown above that may be used to handle the behavior of the promise
+  - `mutationState`: A query status object containing the current loading state and metadata about the request, or the values returned by the `selectFromResult` option where applicable
 
 #### Description
 
-A React hook that lets you trigger an update request for a given endpoint, and subscribes the component to read the request status from the Redux store. The component will re-render as the loading status changes.
+[summary](docblock://query/react/buildHooks.ts?token=UseMutation)
 
 ## `useQueryState`
 
-TBD
+#### Signature
+
+```ts
+type UseQueryState = (
+  arg: any,
+  options?: UseQueryStateOptions
+) => UseQueryStateResult | SelectedQueryStateResult
+
+type UseQueryStateOptions = {
+  skip?: boolean
+  selectFromResult?: (
+    state,
+    lastResult,
+    defaultQueryStateSelector
+  ) => SelectedQueryStateResult
+}
+
+type UseQueryStateResult<T> = {
+  // Base query state
+  originalArgs?: unknown // Arguments passed to the query
+  data?: T // Returned result if present
+  error?: unknown // Error result if present
+  requestId?: string // A string generated by RTK Query
+  endpointName?: string // The name of the given endpoint for the query
+  startedTimeStamp?: number // Timestamp for when the query was initiated
+  fulfilledTimeStamp?: number // Timestamp for when the query was completed
+
+  isUninitialized: false // Query has not started yet.
+  isLoading: false // Query is currently loading for the first time. No data yet.
+  isFetching: false // Query is currently fetching, but might have data from an earlier request.
+  isSuccess: false // Query has data from a successful load.
+  isError: false // Query is currently in an "error" state.
+}
+```
+
+- **Parameters**
+
+  - `arg`: The argument passed to the query defined in the endpoint
+  - `options`: A set of options that control the return value for the hook
+
+- **Returns**
+  - A query result object containing the current loading state, the actual data or error returned from the API call and metadata about the request. Can be customized with `selectFromResult`
+
+#### Description
+
+[summary](docblock://query/react/buildHooks.ts?token=UseQueryState)
 
 ## `useQuerySubscription`
 
-TBD
+#### Signature
+
+```ts
+type UseQuerySubscription = (
+  arg: any,
+  options?: UseQuerySubscriptionOptions
+) => UseQuerySubscriptionResult
+
+type UseQuerySubscriptionOptions = {
+  skip?: boolean
+  refetchOnMountOrArgChange?: boolean | number
+  pollingInterval?: number
+  refetchOnReconnect?: boolean
+  refetchOnFocus?: boolean
+}
+
+type UseQuerySubscriptionResult = {
+  refetch: () => void // A function to force refetch the query
+}
+```
+
+- **Parameters**
+
+  - `arg`: The argument passed to the query defined in the endpoint
+  - `options`: A set of options that control the fetching behaviour of the hook
+
+- **Returns**
+  - An object containing a function to `refetch` the data
+
+#### Description
+
+[summary](docblock://query/react/buildHooks.ts?token=UseQuerySubscription)
 
 ## `useLazyQuery`
 
-TBD
+#### Signature
+
+```ts
+type UseLazyQuery = (
+  options?: UseLazyQueryOptions
+) => [UseLazyQueryTrigger, UseQueryStateResult, UseLazyQueryLastPromiseInfo]
+
+type UseLazyQueryOptions = {
+  pollingInterval?: number
+  refetchOnReconnect?: boolean
+  refetchOnFocus?: boolean
+  selectFromResult?: (
+    state,
+    lastResult,
+    defaultQueryStateSelector
+  ) => UseQueryStateResult
+}
+
+type UseLazyQueryTrigger = (arg: any) => void
+
+type UseQueryStateResult<T> = {
+  // Base query state
+  originalArgs?: unknown // Arguments passed to the query
+  data?: T // Returned result if present
+  error?: unknown // Error result if present
+  requestId?: string // A string generated by RTK Query
+  endpointName?: string // The name of the given endpoint for the query
+  startedTimeStamp?: number // Timestamp for when the query was initiated
+  fulfilledTimeStamp?: number // Timestamp for when the query was completed
+
+  isUninitialized: false // Query has not started yet.
+  isLoading: false // Query is currently loading for the first time. No data yet.
+  isFetching: false // Query is currently fetching, but might have data from an earlier request.
+  isSuccess: false // Query has data from a successful load.
+  isError: false // Query is currently in an "error" state.
+}
+
+type UseLazyQueryLastPromiseInfo = {
+  lastArg: any
+}
+```
+
+- **Parameters**
+
+  - `options`: A set of options that control the fetching behavior and returned result value of the hook. Options affecting fetching behavior will only have an effect after the lazy query has been triggered at least once.
+
+- **Returns**: A tuple containing:
+  - `trigger`: A function that fetches the corresponding data for the endpoint when called
+  - `result`: A query result object containing the current loading state, the actual data or error returned from the API call and metadata about the request. Can be customized with `selectFromResult`
+  - `lastPromiseInfo`: An object containing the last argument used to call the trigger function
+
+#### Description
+
+[summary](docblock://query/react/buildHooks.ts?token=UseLazyQuery)
 
 ## `useLazyQuerySubscription`
 
-TBD
+#### Signature
+
+```ts
+type UseLazyQuerySubscription = (
+  options?: UseLazyQuerySubscriptionOptions
+) => [UseLazyQuerySubscriptionTrigger, LastArg]
+
+type UseLazyQuerySubscriptionOptions = {
+  pollingInterval?: number
+  refetchOnReconnect?: boolean
+  refetchOnFocus?: boolean
+}
+
+type UseLazyQuerySubscriptionTrigger = (arg: any) => void
+```
+
+- **Parameters**
+
+  - `options`: A set of options that control the fetching behavior of the hook. The options will only have an effect after the lazy query has been triggered at least once.
+
+- **Returns**: A tuple containing:
+  - `trigger`: A function that fetches the corresponding data for the endpoint when called
+  - `lastArg`: The last argument used to call the trigger function
+
+#### Description
+
+[summary](docblock://query/react/buildHooks.ts?token=UseLazyQuerySubscription)
 
 ## `usePrefetch`
 
-TBD
+#### Signature
+
+```ts
+type UsePrefetch = (
+  endpointName: string,
+  options?: UsePrefetchOptions
+) => PrefetchCallback
+
+type UsePrefetchOptions =
+  | {
+      // If specified, only runs the query if the difference between `new Date()` and the last
+      // `fulfilledTimeStamp` is greater than the given value (in seconds)
+      ifOlderThan?: false | number
+    }
+  | {
+      // If `force: true`, it will ignore the `ifOlderThan` value if it is set and the query
+      // will be run even if it exists in the cache.
+      force?: boolean
+    }
+
+type PrefetchCallback = (arg: any, options?: UsePrefetchOptions) => void
+```
+
+- **Parameters**
+
+  - `endpointName`: The name of the endpoint to prefetch data for
+  - `options`: A set of options that control whether the prefetch request should occur
+
+- **Returns**
+  - A `prefetch` callback that when called, will initiate fetching the data for the provided endpoint
+
+#### Description
+
+A React hook which can be used to initiate fetching data ahead of time.
+
+#### Features
+
+- Manual control over firing a request to retrieve data
diff --git a/docs/api/rtk-query/created-api/redux-integration.md b/docs/api/rtk-query/created-api/redux-integration.md
index 6c41afbe..55eba92e 100644
--- a/docs/api/rtk-query/created-api/redux-integration.md
+++ b/docs/api/rtk-query/created-api/redux-integration.md
@@ -12,8 +12,8 @@ Internally, `createApi` will call [the Redux Toolkit `createSlice` API](https://
 The generated slice reducer and the middleware both need to be added to your Redux store setup in `configureStore` in order to work correctly:
 
 ```ts title="src/store.ts"
-import { configureStore, setupListeners } from '@reduxjs/toolkit';
-import { pokemonApi } from './services/pokemon';
+import { configureStore, setupListeners } from '@reduxjs/toolkit'
+import { pokemonApi } from './services/pokemon'
 
 export const store = configureStore({
   reducer: {
@@ -22,14 +22,15 @@ export const store = configureStore({
   },
   // Adding the api middleware enables caching, invalidation, polling,
   // and other useful features of `rtk-query`.
-  middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(pokemonApi.middleware),
-});
+  middleware: (getDefaultMiddleware) =>
+    getDefaultMiddleware().concat(pokemonApi.middleware),
+})
 ```
 
 ## `reducerPath`
 
 ```ts
-reducerPath: string;
+reducerPath: string
 ```
 
 Contains the `reducerPath` option provided to `createApi`. Use this as the root state key when adding the `reducer` function to the store so that the rest of the generated API logic can find the state correctly.
@@ -37,7 +38,7 @@ Contains the `reducerPath` option provided to `createApi`. Use this as the root
 ## `reducer`
 
 ```ts
-reducer: Reducer;
+reducer: Reducer
 ```
 
 A standard Redux slice reducer function containing the logic for updating the cached data. Add this to the Redux store using the `reducerPath` you provided as the root state key.
@@ -45,7 +46,7 @@ A standard Redux slice reducer function containing the logic for updating the ca
 ## `middleware`
 
 ```ts
-middleware: Middleware;
+middleware: Middleware
 ```
 
 A custom Redux middleware that contains logic for managing caching, invalidation, subscriptions, polling, and more. Add this to the store setup after other middleware.
diff --git a/docs/api/rtk-query/setupListeners.md b/docs/api/rtk-query/setupListeners.md
index 515d3f0d..4053859e 100644
--- a/docs/api/rtk-query/setupListeners.md
+++ b/docs/api/rtk-query/setupListeners.md
@@ -11,60 +11,66 @@ hide_table_of_contents: false
 A utility used to enable `refetchOnMount` and `refetchOnReconnect` behaviors. It requires the `dispatch` method from your store. Calling `setupListeners(store.dispatch)` will configure listeners with the recommended defaults, but you have the option of providing a callback for more granular control.
 
 ```ts title="setupListeners default configuration"
-let initialized = false;
+let initialized = false
 export function setupListeners(
   dispatch: ThunkDispatch<any, any, any>,
   customHandler?: (
     dispatch: ThunkDispatch<any, any, any>,
     actions: {
-      onFocus: typeof onFocus;
-      onFocusLost: typeof onFocusLost;
-      onOnline: typeof onOnline;
-      onOffline: typeof onOffline;
+      onFocus: typeof onFocus
+      onFocusLost: typeof onFocusLost
+      onOnline: typeof onOnline
+      onOffline: typeof onOffline
     }
   ) => () => void
 ) {
   function defaultHandler() {
-    const handleFocus = () => dispatch(onFocus());
-    const handleFocusLost = () => dispatch(onFocusLost());
-    const handleOnline = () => dispatch(onOnline());
-    const handleOffline = () => dispatch(onOffline());
+    const handleFocus = () => dispatch(onFocus())
+    const handleFocusLost = () => dispatch(onFocusLost())
+    const handleOnline = () => dispatch(onOnline())
+    const handleOffline = () => dispatch(onOffline())
     const handleVisibilityChange = () => {
       if (window.document.visibilityState === 'visible') {
-        handleFocus();
+        handleFocus()
       } else {
-        handleFocusLost();
+        handleFocusLost()
       }
-    };
+    }
 
     if (!initialized) {
       if (typeof window !== 'undefined' && window.addEventListener) {
         // Handle focus events
-        window.addEventListener('visibilitychange', handleVisibilityChange, false);
-        window.addEventListener('focus', handleFocus, false);
+        window.addEventListener(
+          'visibilitychange',
+          handleVisibilityChange,
+          false
+        )
+        window.addEventListener('focus', handleFocus, false)
 
         // Handle connection events
-        window.addEventListener('online', handleOnline, false);
-        window.addEventListener('offline', handleOffline, false);
-        initialized = true;
+        window.addEventListener('online', handleOnline, false)
+        window.addEventListener('offline', handleOffline, false)
+        initialized = true
       }
     }
     const unsubscribe = () => {
-      window.removeEventListener('focus', handleFocus);
-      window.removeEventListener('visibilitychange', handleVisibilityChange);
-      window.removeEventListener('online', handleOnline);
-      window.removeEventListener('offline', handleOffline);
-      initialized = false;
-    };
-    return unsubscribe;
+      window.removeEventListener('focus', handleFocus)
+      window.removeEventListener('visibilitychange', handleVisibilityChange)
+      window.removeEventListener('online', handleOnline)
+      window.removeEventListener('offline', handleOffline)
+      initialized = false
+    }
+    return unsubscribe
   }
 
-  return customHandler ? customHandler(dispatch, { onFocus, onFocusLost, onOffline, onOnline }) : defaultHandler();
+  return customHandler
+    ? customHandler(dispatch, { onFocus, onFocusLost, onOffline, onOnline })
+    : defaultHandler()
 }
 ```
 
 If you notice, `onFocus`, `onFocusLost`, `onOffline`, `onOnline` are all actions that are provided to the callback. Additionally, these actions are made available to `api.internalActions` and are able to be used by dispatching them like this:
 
 ```ts title="Manual onFocus event"
-dispatch(api.internalActions.onFocus());
+dispatch(api.internalActions.onFocus())
 ```
diff --git a/docs/usage/rtk-query/code-generation.md b/docs/usage/rtk-query/code-generation.md
index c2d6ff92..c6c444d2 100644
--- a/docs/usage/rtk-query/code-generation.md
+++ b/docs/usage/rtk-query/code-generation.md
@@ -21,7 +21,7 @@ npx @rtk-incubator/rtk-query-codegen-openapi petstore.json > petstore-api.genera
 We recommend placing these generated types in one file that you do not modify (so you can constantly re-generate it when your API definition changes) and creating a second file to enhance it with additional info:
 
 ```ts title="petstore-api.ts"
-import { api as generatedApi } from './petstore-api.generated';
+import { api as generatedApi } from './petstore-api.generated'
 
 export const api = generatedApi.enhanceEndpoints({
   addTagTypes: ['Pet'],
@@ -35,13 +35,16 @@ export const api = generatedApi.enhanceEndpoints({
         // is result available?
         result
           ? // successful query
-            [{ type: 'Pet', id: 'LIST' }, ...result.map((pet) => ({ type: 'Pet' as const, id: pet.id }))]
+            [
+              { type: 'Pet', id: 'LIST' },
+              ...result.map((pet) => ({ type: 'Pet' as const, id: pet.id })),
+            ]
           : // an error occurred, but we still want to refetch this query when `{ type: 'Pet', id: 'LIST' }` is invalidated
             [{ type: 'Pet', id: 'LIST' }],
     },
     // alternate notation: callback that gets passed in `endpoint` - you can freely modify the object here
     addPet: (endpoint) => {
-      endpoint.invalidatesTags = (result) => [{ type: 'Pet', id: result.id }];
+      endpoint.invalidatesTags = (result) => [{ type: 'Pet', id: result.id }]
     },
     updatePet: {
       invalidatesTags: (result, error, arg) => [{ type: 'Pet', id: arg.petId }],
@@ -50,7 +53,7 @@ export const api = generatedApi.enhanceEndpoints({
       invalidatesTags: (result, error, arg) => [{ type: 'Pet', id: arg.petId }],
     },
   },
-});
+})
 
 export const {
   useGetPetByIdQuery,
@@ -58,5 +61,5 @@ export const {
   useAddPetMutation,
   useUpdatePetMutation,
   useDeletePetMutation,
-} = api;
+} = api
 ```
diff --git a/docs/usage/rtk-query/queries.md b/docs/usage/rtk-query/queries.md
index d27f4643..c9cb823e 100644
--- a/docs/usage/rtk-query/queries.md
+++ b/docs/usage/rtk-query/queries.md
@@ -40,14 +40,18 @@ Hooks are automatically generated based on the name of the `endpoint` in the ser
 
 #### Hook types
 
-There are 3 query-related hooks:
+There are 5 query-related hooks:
 
-1. `useQuery`
-   - Composes `useQuerySubscription` and `useQueryState` and is the primary hook.
-2. `useQuerySubscription`
+1. [`useQuery`](../../api/rtk-query/created-api/hooks/#usequery)
+   - Composes `useQuerySubscription` and `useQueryState` and is the primary hook
+2. [`useQuerySubscription`](../../api/rtk-query/created-api/hooks/#usequerysubscription)
    - Returns a `refetch` function and accepts all hook options
-3. `useQueryState`
+3. [`useQueryState`](../../api/rtk-query/created-api/hooks/#usequerystate)
    - Returns the query state and accepts `skip` and `selectFromResult`
+4. [`useLazyQuery`](../../api/rtk-query/created-api/hooks/#uselazyquery)
+   - Returns a tuple with a `fetch` function, the query result, and last promise info
+5. [`useLazyQuerySubscription`](../../api/rtk-query/created-api/hooks/#uselazyquerysubscription)
+   - Returns a tuple with a `fetch` function, and last promise info
 
 #### Query Hook Options
 
@@ -64,7 +68,6 @@ There are 3 query-related hooks:
 
 ```ts title="All returned elements"
 // Base query state
-status: 'uninitialized'|'pending'|'fulfilled'|'rejected'; // @deprecated - A string describing the query state
 originalArgs?: unknown; // Arguments passed to the query
 data?: unknown; // Returned result if present
 error?: unknown; // Error result if present
diff --git a/etc/rtk-query-react.api.md b/etc/rtk-query-react.api.md
index ea0a452b..25a54e1b 100644
--- a/etc/rtk-query-react.api.md
+++ b/etc/rtk-query-react.api.md
@@ -1,167 +1,170 @@
-## API Report File for "@reduxjs/toolkit"
-
-> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
-
-```ts
-
-import { ActionCreatorWithoutPayload } from '@reduxjs/toolkit';
-import { AnyAction } from '@reduxjs/toolkit';
-import { batch } from 'react-redux';
-import { Context } from 'react';
-import { ReactReduxContextValue } from 'react-redux';
-import { SerializedError } from '@reduxjs/toolkit';
-import { ThunkDispatch } from '@reduxjs/toolkit';
-import { useDispatch } from 'react-redux';
-import { useSelector } from 'react-redux';
-import { useStore } from 'react-redux';
-
-// @public (undocumented)
-export type Api<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string, Enhancers extends ModuleName = CoreModule> = Id<Id<UnionToIntersection<ApiModules<BaseQuery, Definitions, ReducerPath, TagTypes>[Enhancers]>> & {
-    injectEndpoints<NewDefinitions extends EndpointDefinitions>(_: {
-        endpoints: (build: EndpointBuilder<BaseQuery, TagTypes, ReducerPath>) => NewDefinitions;
-        overrideExisting?: boolean;
-    }): Api<BaseQuery, Definitions & NewDefinitions, ReducerPath, TagTypes, Enhancers>;
-    enhanceEndpoints<NewTagTypes extends string = never>(_: {
-        addEntityTypes?: readonly NewTagTypes[];
-        addTagTypes?: readonly NewTagTypes[];
-        endpoints?: ReplaceTagTypes<Definitions, TagTypes | NoInfer<NewTagTypes>> extends infer NewDefinitions ? {
-            [K in keyof NewDefinitions]?: Partial<NewDefinitions[K]> | ((definition: NewDefinitions[K]) => void);
-        } : never;
-    }): Api<BaseQuery, ReplaceTagTypes<Definitions, TagTypes | NewTagTypes>, ReducerPath, TagTypes | NewTagTypes, Enhancers>;
-}>;
-
-// @public (undocumented)
-export interface ApiModules<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string> {
-}
-
-// @public
-export function ApiProvider<A extends Api<any, {}, any, any>>(props: {
-    children: any;
-    api: A;
-    setupListeners?: Parameters<typeof setupListeners>[1];
-    context?: Context<ReactReduxContextValue>;
-}): JSX.Element;
-
-// @public (undocumented)
-export type ApiWithInjectedEndpoints<ApiDefinition extends Api<any, any, any, any>, Injections extends ApiDefinition extends Api<infer B, any, infer R, infer E> ? [Api<B, any, R, E>, ...Api<B, any, R, E>[]] : never> = Omit<ApiDefinition, 'endpoints'> & Omit<Injections, 'endpoints'> & {
-    endpoints: ApiDefinition['endpoints'] & Partial<UnionToIntersection<Injections[number]['endpoints']>>;
-};
-
-// @public (undocumented)
-export type BaseQueryEnhancer<AdditionalArgs = unknown, AdditionalDefinitionExtraOptions = unknown, Config = void> = <BaseQuery extends BaseQueryFn>(baseQuery: BaseQuery, config: Config) => BaseQueryFn<BaseQueryArg<BaseQuery> & AdditionalArgs, BaseQueryResult<BaseQuery>, BaseQueryError<BaseQuery>, BaseQueryExtraOptions<BaseQuery> & AdditionalDefinitionExtraOptions>;
-
-// @public (undocumented)
-export type BaseQueryFn<Args = any, Result = unknown, Error = unknown, DefinitionExtraOptions = {}, Meta = {}> = (args: Args, api: BaseQueryApi, extraOptions: DefinitionExtraOptions) => MaybePromise<QueryReturnValue<Result, Error, Meta>>;
-
-// @public
-export function buildCreateApi<Modules extends [Module<any>, ...Module<any>[]]>(...modules: Modules): CreateApi<Modules[number]['name']>;
-
-// @public
-export const coreModule: () => Module<CoreModule>;
-
-// @public (undocumented)
-export type CreateApi<Modules extends ModuleName> = {
-    <BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', TagTypes extends string = never>(options: CreateApiOptions<BaseQuery, Definitions, ReducerPath, TagTypes>): Api<BaseQuery, Definitions, ReducerPath, TagTypes, Modules>;
-};
-
-// @public (undocumented)
-export const createApi: CreateApi<typeof coreModuleName | typeof reactHooksModuleName>;
-
-// @public (undocumented)
-export interface CreateApiOptions<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', TagTypes extends string = never> {
-    baseQuery: BaseQuery;
-    endpoints(build: EndpointBuilder<BaseQuery, TagTypes, ReducerPath>): Definitions;
-    // @deprecated (undocumented)
-    entityTypes?: readonly TagTypes[];
-    keepUnusedDataFor?: number;
-    reducerPath?: ReducerPath;
-    refetchOnFocus?: boolean;
-    refetchOnMountOrArgChange?: boolean | number;
-    refetchOnReconnect?: boolean;
-    serializeQueryArgs?: SerializeQueryArgs<BaseQueryArg<BaseQuery>>;
-    tagTypes?: readonly TagTypes[];
-}
-
-// @public (undocumented)
-export type EndpointDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string> = QueryDefinition<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath> | MutationDefinition<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath>;
-
-// @public (undocumented)
-export type EndpointDefinitions = Record<string, EndpointDefinition<any, any, any, any>>;
-
-// @public
-export function fakeBaseQuery<ErrorType>(): BaseQueryFn<void, NEVER, ErrorType, {}>;
-
-// @public (undocumented)
-export interface FetchArgs extends CustomRequestInit {
-    // (undocumented)
-    body?: any;
-    // (undocumented)
-    params?: Record<string, any>;
-    // (undocumented)
-    responseHandler?: ResponseHandler;
-    // (undocumented)
-    url: string;
-    // (undocumented)
-    validateStatus?: (response: Response, body: any) => boolean;
-}
-
-// @public
-export function fetchBaseQuery({ baseUrl, prepareHeaders, fetchFn, ...baseFetchOptions }?: FetchBaseQueryArgs): BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>;
-
-// @public (undocumented)
-export interface FetchBaseQueryError {
-    // (undocumented)
-    data: unknown;
-    // (undocumented)
-    status: number;
-}
-
-// @public (undocumented)
-export type Module<Name extends ModuleName> = {
-    name: Name;
-    init<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string>(api: Api<BaseQuery, EndpointDefinitions, ReducerPath, TagTypes, ModuleName>, options: Required<CreateApiOptions<BaseQuery, Definitions, ReducerPath, TagTypes>>, context: ApiContext<Definitions>): {
-        injectEndpoint(endpointName: string, definition: EndpointDefinition<any, any, any, any>): void;
-    };
-};
-
-// @public (undocumented)
-export type MutationDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string, Context = Record<string, any>> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType> & MutationExtraOptions<TagTypes, ResultType, QueryArg, BaseQuery, ReducerPath, Context>;
-
-// @public (undocumented)
-export type QueryDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string, Context = Record<string, any>> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType> & QueryExtraOptions<TagTypes, ResultType, QueryArg, BaseQuery, ReducerPath, Context>;
-
-// @public
-export enum QueryStatus {
-    // (undocumented)
-    fulfilled = "fulfilled",
-    // (undocumented)
-    pending = "pending",
-    // (undocumented)
-    rejected = "rejected",
-    // (undocumented)
-    uninitialized = "uninitialized"
-}
-
-// @public
-export const reactHooksModule: ({ batch, useDispatch, useSelector, useStore, }?: ReactHooksModuleOptions) => Module<ReactHooksModule>;
-
-// @public
-export const retry: BaseQueryEnhancer<unknown, StaggerOptions, void | StaggerOptions> & {
-    fail: typeof fail_2;
-};
-
-// @public
-export function setupListeners(dispatch: ThunkDispatch<any, any, any>, customHandler?: (dispatch: ThunkDispatch<any, any, any>, actions: {
-    onFocus: typeof onFocus;
-    onFocusLost: typeof onFocusLost;
-    onOnline: typeof onOnline;
-    onOffline: typeof onOffline;
-}) => () => void): () => void;
-
-// @public (undocumented)
-export const skipSelector: unique symbol;
-
-
-// (No @packageDocumentation comment for this package)
-
-```
+## API Report File for "@reduxjs/toolkit"
+
+> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
+
+```ts
+
+import { ActionCreatorWithoutPayload } from '@reduxjs/toolkit';
+import { AnyAction } from '@reduxjs/toolkit';
+import { batch } from 'react-redux';
+import { Context } from 'react';
+import { ReactReduxContextValue } from 'react-redux';
+import { SerializedError } from '@reduxjs/toolkit';
+import { ThunkDispatch } from '@reduxjs/toolkit';
+import { useDispatch } from 'react-redux';
+import { useSelector } from 'react-redux';
+import { useStore } from 'react-redux';
+
+// @public (undocumented)
+export type Api<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string, Enhancers extends ModuleName = CoreModule> = Id<Id<UnionToIntersection<ApiModules<BaseQuery, Definitions, ReducerPath, TagTypes>[Enhancers]>> & {
+    injectEndpoints<NewDefinitions extends EndpointDefinitions>(_: {
+        endpoints: (build: EndpointBuilder<BaseQuery, TagTypes, ReducerPath>) => NewDefinitions;
+        overrideExisting?: boolean;
+    }): Api<BaseQuery, Definitions & NewDefinitions, ReducerPath, TagTypes, Enhancers>;
+    enhanceEndpoints<NewTagTypes extends string = never>(_: {
+        addEntityTypes?: readonly NewTagTypes[];
+        addTagTypes?: readonly NewTagTypes[];
+        endpoints?: ReplaceTagTypes<Definitions, TagTypes | NoInfer<NewTagTypes>> extends infer NewDefinitions ? {
+            [K in keyof NewDefinitions]?: Partial<NewDefinitions[K]> | ((definition: NewDefinitions[K]) => void);
+        } : never;
+    }): Api<BaseQuery, ReplaceTagTypes<Definitions, TagTypes | NewTagTypes>, ReducerPath, TagTypes | NewTagTypes, Enhancers>;
+}>;
+
+// @public (undocumented)
+export interface ApiModules<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string> {
+}
+
+// @public
+export function ApiProvider<A extends Api<any, {}, any, any>>(props: {
+    children: any;
+    api: A;
+    setupListeners?: Parameters<typeof setupListeners>[1];
+    context?: Context<ReactReduxContextValue>;
+}): JSX.Element;
+
+// @public (undocumented)
+export type ApiWithInjectedEndpoints<ApiDefinition extends Api<any, any, any, any>, Injections extends ApiDefinition extends Api<infer B, any, infer R, infer E> ? [Api<B, any, R, E>, ...Api<B, any, R, E>[]] : never> = Omit<ApiDefinition, 'endpoints'> & Omit<Injections, 'endpoints'> & {
+    endpoints: ApiDefinition['endpoints'] & Partial<UnionToIntersection<Injections[number]['endpoints']>>;
+};
+
+// @public (undocumented)
+export type BaseQueryEnhancer<AdditionalArgs = unknown, AdditionalDefinitionExtraOptions = unknown, Config = void> = <BaseQuery extends BaseQueryFn>(baseQuery: BaseQuery, config: Config) => BaseQueryFn<BaseQueryArg<BaseQuery> & AdditionalArgs, BaseQueryResult<BaseQuery>, BaseQueryError<BaseQuery>, BaseQueryExtraOptions<BaseQuery> & AdditionalDefinitionExtraOptions>;
+
+// @public (undocumented)
+export type BaseQueryFn<Args = any, Result = unknown, Error = unknown, DefinitionExtraOptions = {}, Meta = {}> = (args: Args, api: BaseQueryApi, extraOptions: DefinitionExtraOptions) => MaybePromise<QueryReturnValue<Result, Error, Meta>>;
+
+// @public
+export function buildCreateApi<Modules extends [Module<any>, ...Module<any>[]]>(...modules: Modules): CreateApi<Modules[number]['name']>;
+
+// @public (undocumented)
+export function copyWithStructuralSharing<T>(oldObj: any, newObj: T): T;
+
+// @public
+export const coreModule: () => Module<CoreModule>;
+
+// @public (undocumented)
+export type CreateApi<Modules extends ModuleName> = {
+    <BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', TagTypes extends string = never>(options: CreateApiOptions<BaseQuery, Definitions, ReducerPath, TagTypes>): Api<BaseQuery, Definitions, ReducerPath, TagTypes, Modules>;
+};
+
+// @public (undocumented)
+export const createApi: CreateApi<typeof coreModuleName | typeof reactHooksModuleName>;
+
+// @public (undocumented)
+export interface CreateApiOptions<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', TagTypes extends string = never> {
+    baseQuery: BaseQuery;
+    endpoints(build: EndpointBuilder<BaseQuery, TagTypes, ReducerPath>): Definitions;
+    // @deprecated (undocumented)
+    entityTypes?: readonly TagTypes[];
+    keepUnusedDataFor?: number;
+    reducerPath?: ReducerPath;
+    refetchOnFocus?: boolean;
+    refetchOnMountOrArgChange?: boolean | number;
+    refetchOnReconnect?: boolean;
+    serializeQueryArgs?: SerializeQueryArgs<BaseQueryArg<BaseQuery>>;
+    tagTypes?: readonly TagTypes[];
+}
+
+// @public (undocumented)
+export type EndpointDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string> = QueryDefinition<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath> | MutationDefinition<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath>;
+
+// @public (undocumented)
+export type EndpointDefinitions = Record<string, EndpointDefinition<any, any, any, any>>;
+
+// @public
+export function fakeBaseQuery<ErrorType>(): BaseQueryFn<void, NEVER, ErrorType, {}>;
+
+// @public (undocumented)
+export interface FetchArgs extends CustomRequestInit {
+    // (undocumented)
+    body?: any;
+    // (undocumented)
+    params?: Record<string, any>;
+    // (undocumented)
+    responseHandler?: ResponseHandler;
+    // (undocumented)
+    url: string;
+    // (undocumented)
+    validateStatus?: (response: Response, body: any) => boolean;
+}
+
+// @public
+export function fetchBaseQuery({ baseUrl, prepareHeaders, fetchFn, ...baseFetchOptions }?: FetchBaseQueryArgs): BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>;
+
+// @public (undocumented)
+export interface FetchBaseQueryError {
+    // (undocumented)
+    data: unknown;
+    // (undocumented)
+    status: number;
+}
+
+// @public (undocumented)
+export type Module<Name extends ModuleName> = {
+    name: Name;
+    init<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string>(api: Api<BaseQuery, EndpointDefinitions, ReducerPath, TagTypes, ModuleName>, options: Required<CreateApiOptions<BaseQuery, Definitions, ReducerPath, TagTypes>>, context: ApiContext<Definitions>): {
+        injectEndpoint(endpointName: string, definition: EndpointDefinition<any, any, any, any>): void;
+    };
+};
+
+// @public (undocumented)
+export type MutationDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string, Context = Record<string, any>> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType> & MutationExtraOptions<TagTypes, ResultType, QueryArg, BaseQuery, ReducerPath, Context>;
+
+// @public (undocumented)
+export type QueryDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string, Context = Record<string, any>> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType> & QueryExtraOptions<TagTypes, ResultType, QueryArg, BaseQuery, ReducerPath, Context>;
+
+// @public
+export enum QueryStatus {
+    // (undocumented)
+    fulfilled = "fulfilled",
+    // (undocumented)
+    pending = "pending",
+    // (undocumented)
+    rejected = "rejected",
+    // (undocumented)
+    uninitialized = "uninitialized"
+}
+
+// @public
+export const reactHooksModule: ({ batch, useDispatch, useSelector, useStore, }?: ReactHooksModuleOptions) => Module<ReactHooksModule>;
+
+// @public
+export const retry: BaseQueryEnhancer<unknown, StaggerOptions, void | StaggerOptions> & {
+    fail: typeof fail_2;
+};
+
+// @public
+export function setupListeners(dispatch: ThunkDispatch<any, any, any>, customHandler?: (dispatch: ThunkDispatch<any, any, any>, actions: {
+    onFocus: typeof onFocus;
+    onFocusLost: typeof onFocusLost;
+    onOnline: typeof onOnline;
+    onOffline: typeof onOffline;
+}) => () => void): () => void;
+
+// @public (undocumented)
+export const skipSelector: unique symbol;
+
+
+// (No @packageDocumentation comment for this package)
+
+```
diff --git a/etc/rtk-query.api.md b/etc/rtk-query.api.md
index 1a046705..53ded28e 100644
--- a/etc/rtk-query.api.md
+++ b/etc/rtk-query.api.md
@@ -1,150 +1,153 @@
-## API Report File for "@reduxjs/toolkit"
-
-> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
-
-```ts
-
-import { ActionCreatorWithoutPayload } from '@reduxjs/toolkit';
-import { AnyAction } from '@reduxjs/toolkit';
-import { SerializedError } from '@reduxjs/toolkit';
-import { ThunkDispatch } from '@reduxjs/toolkit';
-
-// @public (undocumented)
-export type Api<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string, Enhancers extends ModuleName = CoreModule> = Id<Id<UnionToIntersection<ApiModules<BaseQuery, Definitions, ReducerPath, TagTypes>[Enhancers]>> & {
-    injectEndpoints<NewDefinitions extends EndpointDefinitions>(_: {
-        endpoints: (build: EndpointBuilder<BaseQuery, TagTypes, ReducerPath>) => NewDefinitions;
-        overrideExisting?: boolean;
-    }): Api<BaseQuery, Definitions & NewDefinitions, ReducerPath, TagTypes, Enhancers>;
-    enhanceEndpoints<NewTagTypes extends string = never>(_: {
-        addEntityTypes?: readonly NewTagTypes[];
-        addTagTypes?: readonly NewTagTypes[];
-        endpoints?: ReplaceTagTypes<Definitions, TagTypes | NoInfer<NewTagTypes>> extends infer NewDefinitions ? {
-            [K in keyof NewDefinitions]?: Partial<NewDefinitions[K]> | ((definition: NewDefinitions[K]) => void);
-        } : never;
-    }): Api<BaseQuery, ReplaceTagTypes<Definitions, TagTypes | NewTagTypes>, ReducerPath, TagTypes | NewTagTypes, Enhancers>;
-}>;
-
-// @public (undocumented)
-export interface ApiModules<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string> {
-}
-
-// @public (undocumented)
-export type ApiWithInjectedEndpoints<ApiDefinition extends Api<any, any, any, any>, Injections extends ApiDefinition extends Api<infer B, any, infer R, infer E> ? [Api<B, any, R, E>, ...Api<B, any, R, E>[]] : never> = Omit<ApiDefinition, 'endpoints'> & Omit<Injections, 'endpoints'> & {
-    endpoints: ApiDefinition['endpoints'] & Partial<UnionToIntersection<Injections[number]['endpoints']>>;
-};
-
-// @public (undocumented)
-export type BaseQueryEnhancer<AdditionalArgs = unknown, AdditionalDefinitionExtraOptions = unknown, Config = void> = <BaseQuery extends BaseQueryFn>(baseQuery: BaseQuery, config: Config) => BaseQueryFn<BaseQueryArg<BaseQuery> & AdditionalArgs, BaseQueryResult<BaseQuery>, BaseQueryError<BaseQuery>, BaseQueryExtraOptions<BaseQuery> & AdditionalDefinitionExtraOptions>;
-
-// @public (undocumented)
-export type BaseQueryFn<Args = any, Result = unknown, Error = unknown, DefinitionExtraOptions = {}, Meta = {}> = (args: Args, api: BaseQueryApi, extraOptions: DefinitionExtraOptions) => MaybePromise<QueryReturnValue<Result, Error, Meta>>;
-
-// @public
-export function buildCreateApi<Modules extends [Module<any>, ...Module<any>[]]>(...modules: Modules): CreateApi<Modules[number]['name']>;
-
-// @public
-export const coreModule: () => Module<CoreModule>;
-
-// @public (undocumented)
-export type CreateApi<Modules extends ModuleName> = {
-    <BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', TagTypes extends string = never>(options: CreateApiOptions<BaseQuery, Definitions, ReducerPath, TagTypes>): Api<BaseQuery, Definitions, ReducerPath, TagTypes, Modules>;
-};
-
-// @public (undocumented)
-export const createApi: CreateApi<typeof coreModuleName>;
-
-// @public (undocumented)
-export interface CreateApiOptions<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', TagTypes extends string = never> {
-    baseQuery: BaseQuery;
-    endpoints(build: EndpointBuilder<BaseQuery, TagTypes, ReducerPath>): Definitions;
-    // @deprecated (undocumented)
-    entityTypes?: readonly TagTypes[];
-    keepUnusedDataFor?: number;
-    reducerPath?: ReducerPath;
-    refetchOnFocus?: boolean;
-    refetchOnMountOrArgChange?: boolean | number;
-    refetchOnReconnect?: boolean;
-    serializeQueryArgs?: SerializeQueryArgs<BaseQueryArg<BaseQuery>>;
-    tagTypes?: readonly TagTypes[];
-}
-
-// @public (undocumented)
-export type EndpointDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string> = QueryDefinition<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath> | MutationDefinition<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath>;
-
-// @public (undocumented)
-export type EndpointDefinitions = Record<string, EndpointDefinition<any, any, any, any>>;
-
-// @public
-export function fakeBaseQuery<ErrorType>(): BaseQueryFn<void, NEVER, ErrorType, {}>;
-
-// @public (undocumented)
-export interface FetchArgs extends CustomRequestInit {
-    // (undocumented)
-    body?: any;
-    // (undocumented)
-    params?: Record<string, any>;
-    // (undocumented)
-    responseHandler?: ResponseHandler;
-    // (undocumented)
-    url: string;
-    // (undocumented)
-    validateStatus?: (response: Response, body: any) => boolean;
-}
-
-// @public
-export function fetchBaseQuery({ baseUrl, prepareHeaders, fetchFn, ...baseFetchOptions }?: FetchBaseQueryArgs): BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>;
-
-// @public (undocumented)
-export interface FetchBaseQueryError {
-    // (undocumented)
-    data: unknown;
-    // (undocumented)
-    status: number;
-}
-
-// @public (undocumented)
-export type Module<Name extends ModuleName> = {
-    name: Name;
-    init<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string>(api: Api<BaseQuery, EndpointDefinitions, ReducerPath, TagTypes, ModuleName>, options: Required<CreateApiOptions<BaseQuery, Definitions, ReducerPath, TagTypes>>, context: ApiContext<Definitions>): {
-        injectEndpoint(endpointName: string, definition: EndpointDefinition<any, any, any, any>): void;
-    };
-};
-
-// @public (undocumented)
-export type MutationDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string, Context = Record<string, any>> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType> & MutationExtraOptions<TagTypes, ResultType, QueryArg, BaseQuery, ReducerPath, Context>;
-
-// @public (undocumented)
-export type QueryDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string, Context = Record<string, any>> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType> & QueryExtraOptions<TagTypes, ResultType, QueryArg, BaseQuery, ReducerPath, Context>;
-
-// @public
-export enum QueryStatus {
-    // (undocumented)
-    fulfilled = "fulfilled",
-    // (undocumented)
-    pending = "pending",
-    // (undocumented)
-    rejected = "rejected",
-    // (undocumented)
-    uninitialized = "uninitialized"
-}
-
-// @public
-export const retry: BaseQueryEnhancer<unknown, StaggerOptions, void | StaggerOptions> & {
-    fail: typeof fail_2;
-};
-
-// @public
-export function setupListeners(dispatch: ThunkDispatch<any, any, any>, customHandler?: (dispatch: ThunkDispatch<any, any, any>, actions: {
-    onFocus: typeof onFocus;
-    onFocusLost: typeof onFocusLost;
-    onOnline: typeof onOnline;
-    onOffline: typeof onOffline;
-}) => () => void): () => void;
-
-// @public (undocumented)
-export const skipSelector: unique symbol;
-
-
-// (No @packageDocumentation comment for this package)
-
-```
+## API Report File for "@reduxjs/toolkit"
+
+> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
+
+```ts
+
+import { ActionCreatorWithoutPayload } from '@reduxjs/toolkit';
+import { AnyAction } from '@reduxjs/toolkit';
+import { SerializedError } from '@reduxjs/toolkit';
+import { ThunkDispatch } from '@reduxjs/toolkit';
+
+// @public (undocumented)
+export type Api<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string, Enhancers extends ModuleName = CoreModule> = Id<Id<UnionToIntersection<ApiModules<BaseQuery, Definitions, ReducerPath, TagTypes>[Enhancers]>> & {
+    injectEndpoints<NewDefinitions extends EndpointDefinitions>(_: {
+        endpoints: (build: EndpointBuilder<BaseQuery, TagTypes, ReducerPath>) => NewDefinitions;
+        overrideExisting?: boolean;
+    }): Api<BaseQuery, Definitions & NewDefinitions, ReducerPath, TagTypes, Enhancers>;
+    enhanceEndpoints<NewTagTypes extends string = never>(_: {
+        addEntityTypes?: readonly NewTagTypes[];
+        addTagTypes?: readonly NewTagTypes[];
+        endpoints?: ReplaceTagTypes<Definitions, TagTypes | NoInfer<NewTagTypes>> extends infer NewDefinitions ? {
+            [K in keyof NewDefinitions]?: Partial<NewDefinitions[K]> | ((definition: NewDefinitions[K]) => void);
+        } : never;
+    }): Api<BaseQuery, ReplaceTagTypes<Definitions, TagTypes | NewTagTypes>, ReducerPath, TagTypes | NewTagTypes, Enhancers>;
+}>;
+
+// @public (undocumented)
+export interface ApiModules<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string> {
+}
+
+// @public (undocumented)
+export type ApiWithInjectedEndpoints<ApiDefinition extends Api<any, any, any, any>, Injections extends ApiDefinition extends Api<infer B, any, infer R, infer E> ? [Api<B, any, R, E>, ...Api<B, any, R, E>[]] : never> = Omit<ApiDefinition, 'endpoints'> & Omit<Injections, 'endpoints'> & {
+    endpoints: ApiDefinition['endpoints'] & Partial<UnionToIntersection<Injections[number]['endpoints']>>;
+};
+
+// @public (undocumented)
+export type BaseQueryEnhancer<AdditionalArgs = unknown, AdditionalDefinitionExtraOptions = unknown, Config = void> = <BaseQuery extends BaseQueryFn>(baseQuery: BaseQuery, config: Config) => BaseQueryFn<BaseQueryArg<BaseQuery> & AdditionalArgs, BaseQueryResult<BaseQuery>, BaseQueryError<BaseQuery>, BaseQueryExtraOptions<BaseQuery> & AdditionalDefinitionExtraOptions>;
+
+// @public (undocumented)
+export type BaseQueryFn<Args = any, Result = unknown, Error = unknown, DefinitionExtraOptions = {}, Meta = {}> = (args: Args, api: BaseQueryApi, extraOptions: DefinitionExtraOptions) => MaybePromise<QueryReturnValue<Result, Error, Meta>>;
+
+// @public
+export function buildCreateApi<Modules extends [Module<any>, ...Module<any>[]]>(...modules: Modules): CreateApi<Modules[number]['name']>;
+
+// @public (undocumented)
+export function copyWithStructuralSharing<T>(oldObj: any, newObj: T): T;
+
+// @public
+export const coreModule: () => Module<CoreModule>;
+
+// @public (undocumented)
+export type CreateApi<Modules extends ModuleName> = {
+    <BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', TagTypes extends string = never>(options: CreateApiOptions<BaseQuery, Definitions, ReducerPath, TagTypes>): Api<BaseQuery, Definitions, ReducerPath, TagTypes, Modules>;
+};
+
+// @public (undocumented)
+export const createApi: CreateApi<typeof coreModuleName>;
+
+// @public (undocumented)
+export interface CreateApiOptions<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', TagTypes extends string = never> {
+    baseQuery: BaseQuery;
+    endpoints(build: EndpointBuilder<BaseQuery, TagTypes, ReducerPath>): Definitions;
+    // @deprecated (undocumented)
+    entityTypes?: readonly TagTypes[];
+    keepUnusedDataFor?: number;
+    reducerPath?: ReducerPath;
+    refetchOnFocus?: boolean;
+    refetchOnMountOrArgChange?: boolean | number;
+    refetchOnReconnect?: boolean;
+    serializeQueryArgs?: SerializeQueryArgs<BaseQueryArg<BaseQuery>>;
+    tagTypes?: readonly TagTypes[];
+}
+
+// @public (undocumented)
+export type EndpointDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string> = QueryDefinition<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath> | MutationDefinition<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath>;
+
+// @public (undocumented)
+export type EndpointDefinitions = Record<string, EndpointDefinition<any, any, any, any>>;
+
+// @public
+export function fakeBaseQuery<ErrorType>(): BaseQueryFn<void, NEVER, ErrorType, {}>;
+
+// @public (undocumented)
+export interface FetchArgs extends CustomRequestInit {
+    // (undocumented)
+    body?: any;
+    // (undocumented)
+    params?: Record<string, any>;
+    // (undocumented)
+    responseHandler?: ResponseHandler;
+    // (undocumented)
+    url: string;
+    // (undocumented)
+    validateStatus?: (response: Response, body: any) => boolean;
+}
+
+// @public
+export function fetchBaseQuery({ baseUrl, prepareHeaders, fetchFn, ...baseFetchOptions }?: FetchBaseQueryArgs): BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>;
+
+// @public (undocumented)
+export interface FetchBaseQueryError {
+    // (undocumented)
+    data: unknown;
+    // (undocumented)
+    status: number;
+}
+
+// @public (undocumented)
+export type Module<Name extends ModuleName> = {
+    name: Name;
+    init<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string>(api: Api<BaseQuery, EndpointDefinitions, ReducerPath, TagTypes, ModuleName>, options: Required<CreateApiOptions<BaseQuery, Definitions, ReducerPath, TagTypes>>, context: ApiContext<Definitions>): {
+        injectEndpoint(endpointName: string, definition: EndpointDefinition<any, any, any, any>): void;
+    };
+};
+
+// @public (undocumented)
+export type MutationDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string, Context = Record<string, any>> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType> & MutationExtraOptions<TagTypes, ResultType, QueryArg, BaseQuery, ReducerPath, Context>;
+
+// @public (undocumented)
+export type QueryDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string, Context = Record<string, any>> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType> & QueryExtraOptions<TagTypes, ResultType, QueryArg, BaseQuery, ReducerPath, Context>;
+
+// @public
+export enum QueryStatus {
+    // (undocumented)
+    fulfilled = "fulfilled",
+    // (undocumented)
+    pending = "pending",
+    // (undocumented)
+    rejected = "rejected",
+    // (undocumented)
+    uninitialized = "uninitialized"
+}
+
+// @public
+export const retry: BaseQueryEnhancer<unknown, StaggerOptions, void | StaggerOptions> & {
+    fail: typeof fail_2;
+};
+
+// @public
+export function setupListeners(dispatch: ThunkDispatch<any, any, any>, customHandler?: (dispatch: ThunkDispatch<any, any, any>, actions: {
+    onFocus: typeof onFocus;
+    onFocusLost: typeof onFocusLost;
+    onOnline: typeof onOnline;
+    onOffline: typeof onOffline;
+}) => () => void): () => void;
+
+// @public (undocumented)
+export const skipSelector: unique symbol;
+
+
+// (No @packageDocumentation comment for this package)
+
+```
diff --git a/jest.config.js b/jest.config.js
index d8ef40e4..8f445251 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -2,10 +2,12 @@ module.exports = {
   setupFilesAfterEnv: ['./jest.setup.js'],
   testPathIgnorePatterns: ['<rootDir>/query-old/*'],
   moduleNameMapper: {
-    '^@reduxjs/toolkit$': '<rootDir>/src/index.ts',
-    '^@reduxjs/toolkit/query$': '<rootDir>/src/query/index.ts',
-    '^@reduxjs/toolkit/query/react$': '<rootDir>/src/query/react/index.ts',
-    '^@internal/(.*)$': '<rootDir>/src/query/*',
+    '^@reduxjs/toolkit$': '<rootDir>/src/index.ts', // @remap-prod-remove-line
+    '^@reduxjs/toolkit/query$': '<rootDir>/src/query/index.ts', // @remap-prod-remove-line
+    '^@reduxjs/toolkit/query/react$': '<rootDir>/src/query/react/index.ts', // @remap-prod-remove-line
+    // this mapping is disabled as we want `dist` imports in the tests only to be used for "type-only" imports which don't play a role for jest
+    //'^@reduxjs/toolkit/dist/(.*)$': '<rootDir>/src/*',
+    '^@internal/(.*)$': '<rootDir>/src/$1',
   },
   globals: {
     'ts-jest': {
diff --git a/package-lock.json b/package-lock.json
index 0130955a..27bf6b04 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2861,6 +2861,32 @@
         "strict-event-emitter": "^0.2.0"
       }
     },
+    "@nodelib/fs.scandir": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
+      "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==",
+      "dev": true,
+      "requires": {
+        "@nodelib/fs.stat": "2.0.4",
+        "run-parallel": "^1.1.9"
+      }
+    },
+    "@nodelib/fs.stat": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz",
+      "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==",
+      "dev": true
+    },
+    "@nodelib/fs.walk": {
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz",
+      "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==",
+      "dev": true,
+      "requires": {
+        "@nodelib/fs.scandir": "2.1.4",
+        "fastq": "^1.6.0"
+      }
+    },
     "@open-draft/until": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz",
@@ -3485,74 +3511,94 @@
       "dev": true
     },
     "@typescript-eslint/eslint-plugin": {
-      "version": "3.10.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz",
-      "integrity": "sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ==",
+      "version": "4.22.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.22.0.tgz",
+      "integrity": "sha512-U8SP9VOs275iDXaL08Ln1Fa/wLXfj5aTr/1c0t0j6CdbOnxh+TruXu1p4I0NAvdPBQgoPjHsgKn28mOi0FzfoA==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/experimental-utils": "3.10.1",
+        "@typescript-eslint/experimental-utils": "4.22.0",
+        "@typescript-eslint/scope-manager": "4.22.0",
         "debug": "^4.1.1",
         "functional-red-black-tree": "^1.0.1",
+        "lodash": "^4.17.15",
         "regexpp": "^3.0.0",
         "semver": "^7.3.2",
         "tsutils": "^3.17.1"
       }
     },
     "@typescript-eslint/experimental-utils": {
-      "version": "3.10.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz",
-      "integrity": "sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==",
+      "version": "4.22.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.22.0.tgz",
+      "integrity": "sha512-xJXHHl6TuAxB5AWiVrGhvbGL8/hbiCQ8FiWwObO3r0fnvBdrbWEDy1hlvGQOAWc6qsCWuWMKdVWlLAEMpxnddg==",
       "dev": true,
       "requires": {
         "@types/json-schema": "^7.0.3",
-        "@typescript-eslint/types": "3.10.1",
-        "@typescript-eslint/typescript-estree": "3.10.1",
+        "@typescript-eslint/scope-manager": "4.22.0",
+        "@typescript-eslint/types": "4.22.0",
+        "@typescript-eslint/typescript-estree": "4.22.0",
         "eslint-scope": "^5.0.0",
         "eslint-utils": "^2.0.0"
       }
     },
     "@typescript-eslint/parser": {
-      "version": "3.10.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz",
-      "integrity": "sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==",
+      "version": "4.22.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.22.0.tgz",
+      "integrity": "sha512-z/bGdBJJZJN76nvAY9DkJANYgK3nlRstRRi74WHm3jjgf2I8AglrSY+6l7ogxOmn55YJ6oKZCLLy+6PW70z15Q==",
       "dev": true,
       "requires": {
-        "@types/eslint-visitor-keys": "^1.0.0",
-        "@typescript-eslint/experimental-utils": "3.10.1",
-        "@typescript-eslint/types": "3.10.1",
-        "@typescript-eslint/typescript-estree": "3.10.1",
-        "eslint-visitor-keys": "^1.1.0"
+        "@typescript-eslint/scope-manager": "4.22.0",
+        "@typescript-eslint/types": "4.22.0",
+        "@typescript-eslint/typescript-estree": "4.22.0",
+        "debug": "^4.1.1"
+      }
+    },
+    "@typescript-eslint/scope-manager": {
+      "version": "4.22.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.22.0.tgz",
+      "integrity": "sha512-OcCO7LTdk6ukawUM40wo61WdeoA7NM/zaoq1/2cs13M7GyiF+T4rxuA4xM+6LeHWjWbss7hkGXjFDRcKD4O04Q==",
+      "dev": true,
+      "requires": {
+        "@typescript-eslint/types": "4.22.0",
+        "@typescript-eslint/visitor-keys": "4.22.0"
       }
     },
     "@typescript-eslint/types": {
-      "version": "3.10.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.10.1.tgz",
-      "integrity": "sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==",
+      "version": "4.22.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.22.0.tgz",
+      "integrity": "sha512-sW/BiXmmyMqDPO2kpOhSy2Py5w6KvRRsKZnV0c4+0nr4GIcedJwXAq+RHNK4lLVEZAJYFltnnk1tJSlbeS9lYA==",
       "dev": true
     },
     "@typescript-eslint/typescript-estree": {
-      "version": "3.10.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz",
-      "integrity": "sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==",
+      "version": "4.22.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.22.0.tgz",
+      "integrity": "sha512-TkIFeu5JEeSs5ze/4NID+PIcVjgoU3cUQUIZnH3Sb1cEn1lBo7StSV5bwPuJQuoxKXlzAObjYTilOEKRuhR5yg==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/types": "3.10.1",
-        "@typescript-eslint/visitor-keys": "3.10.1",
+        "@typescript-eslint/types": "4.22.0",
+        "@typescript-eslint/visitor-keys": "4.22.0",
         "debug": "^4.1.1",
-        "glob": "^7.1.6",
+        "globby": "^11.0.1",
         "is-glob": "^4.0.1",
-        "lodash": "^4.17.15",
         "semver": "^7.3.2",
         "tsutils": "^3.17.1"
       }
     },
     "@typescript-eslint/visitor-keys": {
-      "version": "3.10.1",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz",
-      "integrity": "sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==",
+      "version": "4.22.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.22.0.tgz",
+      "integrity": "sha512-nnMu4F+s4o0sll6cBSsTeVsT4cwxB7zECK3dFxzEjPBii9xLpq4yqqsy/FU5zMfan6G60DKZSCXAa3sHJZrcYw==",
       "dev": true,
       "requires": {
-        "eslint-visitor-keys": "^1.1.0"
+        "@typescript-eslint/types": "4.22.0",
+        "eslint-visitor-keys": "^2.0.0"
+      },
+      "dependencies": {
+        "eslint-visitor-keys": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz",
+          "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
+          "dev": true
+        }
       }
     },
     "abab": {
@@ -3705,6 +3751,12 @@
         "is-string": "^1.0.5"
       }
     },
+    "array-union": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+      "dev": true
+    },
     "array-unique": {
       "version": "0.3.2",
       "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
@@ -4841,6 +4893,15 @@
       "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==",
       "dev": true
     },
+    "dir-glob": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+      "dev": true,
+      "requires": {
+        "path-type": "^4.0.0"
+      }
+    },
     "doctrine": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
@@ -5641,6 +5702,73 @@
       "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
       "dev": true
     },
+    "fast-glob": {
+      "version": "3.2.5",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
+      "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
+      "dev": true,
+      "requires": {
+        "@nodelib/fs.stat": "^2.0.2",
+        "@nodelib/fs.walk": "^1.2.3",
+        "glob-parent": "^5.1.0",
+        "merge2": "^1.3.0",
+        "micromatch": "^4.0.2",
+        "picomatch": "^2.2.1"
+      },
+      "dependencies": {
+        "braces": {
+          "version": "3.0.2",
+          "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+          "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+          "dev": true,
+          "requires": {
+            "fill-range": "^7.0.1"
+          }
+        },
+        "fill-range": {
+          "version": "7.0.1",
+          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+          "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+          "dev": true,
+          "requires": {
+            "to-regex-range": "^5.0.1"
+          }
+        },
+        "is-number": {
+          "version": "7.0.0",
+          "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+          "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+          "dev": true
+        },
+        "micromatch": {
+          "version": "4.0.4",
+          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
+          "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
+          "dev": true,
+          "requires": {
+            "braces": "^3.0.1",
+            "picomatch": "^2.2.3"
+          },
+          "dependencies": {
+            "picomatch": {
+              "version": "2.2.3",
+              "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz",
+              "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==",
+              "dev": true
+            }
+          }
+        },
+        "to-regex-range": {
+          "version": "5.0.1",
+          "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+          "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+          "dev": true,
+          "requires": {
+            "is-number": "^7.0.0"
+          }
+        }
+      }
+    },
     "fast-json-stable-stringify": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -5653,6 +5781,15 @@
       "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
       "dev": true
     },
+    "fastq": {
+      "version": "1.11.0",
+      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz",
+      "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==",
+      "dev": true,
+      "requires": {
+        "reusify": "^1.0.4"
+      }
+    },
     "fb-watchman": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz",
@@ -6022,6 +6159,34 @@
       "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==",
       "dev": true
     },
+    "globby": {
+      "version": "11.0.3",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz",
+      "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==",
+      "dev": true,
+      "requires": {
+        "array-union": "^2.1.0",
+        "dir-glob": "^3.0.1",
+        "fast-glob": "^3.1.1",
+        "ignore": "^5.1.4",
+        "merge2": "^1.3.0",
+        "slash": "^3.0.0"
+      },
+      "dependencies": {
+        "ignore": {
+          "version": "5.1.8",
+          "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+          "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+          "dev": true
+        },
+        "slash": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+          "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+          "dev": true
+        }
+      }
+    },
     "globrex": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
@@ -10700,6 +10865,12 @@
       "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
       "dev": true
     },
+    "merge2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+      "dev": true
+    },
     "micromatch": {
       "version": "3.1.10",
       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
@@ -11622,6 +11793,12 @@
       "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
       "dev": true
     },
+    "queue-microtask": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+      "dev": true
+    },
     "randombytes": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -12006,6 +12183,12 @@
       "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
       "dev": true
     },
+    "reusify": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+      "dev": true
+    },
     "rimraf": {
       "version": "2.6.3",
       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
@@ -12184,6 +12367,15 @@
       "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
       "dev": true
     },
+    "run-parallel": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+      "dev": true,
+      "requires": {
+        "queue-microtask": "^1.2.2"
+      }
+    },
     "rxjs": {
       "version": "6.6.7",
       "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
@@ -13540,15 +13732,6 @@
       "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==",
       "dev": true
     },
-    "typings-tester": {
-      "version": "0.3.2",
-      "resolved": "https://registry.npmjs.org/typings-tester/-/typings-tester-0.3.2.tgz",
-      "integrity": "sha512-HjGoAM2UoGhmSKKy23TYEKkxlphdJFdix5VvqWFLzH1BJVnnwG38tpC6SXPgqhfFGfHY77RlN1K8ts0dbWBQ7A==",
-      "dev": true,
-      "requires": {
-        "commander": "^2.12.2"
-      }
-    },
     "unbox-primitive": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
diff --git a/package.json b/package.json
index 6f95e768..263747cb 100644
--- a/package.json
+++ b/package.json
@@ -39,8 +39,8 @@
     "@types/react-dom": "^17.0.3",
     "@types/react-redux": "^7.1.16",
     "@types/yargs": "^16.0.1",
-    "@typescript-eslint/eslint-plugin": "^3.9.1",
-    "@typescript-eslint/parser": "^3.9.1",
+    "@typescript-eslint/eslint-plugin": "^4.22.0",
+    "@typescript-eslint/parser": "^4.22.0",
     "axios": "^0.19.2",
     "console-testing-library": "^0.3.1",
     "convert-source-map": "^1.7.0",
@@ -64,7 +64,6 @@
     "tsdx": "^0.14.1",
     "tslib": "^1.10.0",
     "typescript": "^4.2.3",
-    "typings-tester": "^0.3.2",
     "yargs": "^15.3.1"
   },
   "scripts": {
@@ -76,7 +75,7 @@
     "lint": "tsdx lint src",
     "prepare": "npm run build-ci",
     "test": "tsdx test --runInBand",
-    "type-tests": "cd type-tests/files && tsc"
+    "type-tests": "yarn tsc -p src/tests && yarn tsc -p src/query/tests"
   },
   "files": [
     "dist/**/*.js",
diff --git a/scripts/build.ts b/scripts/build.ts
index d6c0cd0b..d7155f0e 100644
--- a/scripts/build.ts
+++ b/scripts/build.ts
@@ -322,7 +322,7 @@ async function main({ skipExtraction = false, local = false }: BuildArgs) {
   // We need one additional package.json file in dist to support
   // versioned types for TS <4.1
   fs.copyFileSync(
-    'src/query/react/versionedTypes/package.json',
+    'src/query/react/versionedTypes/package.dist.json',
     'dist/query/react/versionedTypes/package.json'
   )
 
diff --git a/src/query/core/buildInitiate.ts b/src/query/core/buildInitiate.ts
index 3a6d7d7b..6ed4f24f 100644
--- a/src/query/core/buildInitiate.ts
+++ b/src/query/core/buildInitiate.ts
@@ -179,15 +179,15 @@ export type MutationActionCreatorResult<
   unsubscribe(): void
 }
 
-export function buildInitiate<InternalQueryArgs>({
+export function buildInitiate({
   serializeQueryArgs,
   queryThunk,
   mutationThunk,
   api,
 }: {
-  serializeQueryArgs: InternalSerializeQueryArgs<InternalQueryArgs>
-  queryThunk: AsyncThunk<any, QueryThunkArg<any>, {}>
-  mutationThunk: AsyncThunk<any, MutationThunkArg<any>, {}>
+  serializeQueryArgs: InternalSerializeQueryArgs
+  queryThunk: AsyncThunk<any, QueryThunkArg, {}>
+  mutationThunk: AsyncThunk<any, MutationThunkArg, {}>
   api: Api<any, EndpointDefinitions, any, any>
 }) {
   const {
diff --git a/src/query/core/buildMiddleware.ts b/src/query/core/buildMiddleware.ts
index eddb004d..ef4fc2df 100644
--- a/src/query/core/buildMiddleware.ts
+++ b/src/query/core/buildMiddleware.ts
@@ -52,8 +52,8 @@ export function buildMiddleware<
 }: {
   reducerPath: ReducerPath
   context: ApiContext<Definitions>
-  queryThunk: AsyncThunk<ThunkResult, QueryThunkArg<any>, {}>
-  mutationThunk: AsyncThunk<ThunkResult, MutationThunkArg<any>, {}>
+  queryThunk: AsyncThunk<ThunkResult, QueryThunkArg, {}>
+  mutationThunk: AsyncThunk<ThunkResult, MutationThunkArg, {}>
   api: Api<any, EndpointDefinitions, ReducerPath, TagTypes>
   assertTagType: AssertTagTypes
 }) {
@@ -167,7 +167,7 @@ export function buildMiddleware<
       { status: QueryStatus.uninitialized }
     >,
     queryCacheKey: string,
-    override: Partial<QueryThunkArg<any>> = {}
+    override: Partial<QueryThunkArg> = {}
   ) {
     return queryThunk({
       endpointName: querySubState.endpointName,
diff --git a/src/query/core/buildSelectors.ts b/src/query/core/buildSelectors.ts
index 45435dfe..6feb9622 100644
--- a/src/query/core/buildSelectors.ts
+++ b/src/query/core/buildSelectors.ts
@@ -84,14 +84,13 @@ const defaultMutationSubState = createNextState(
 )
 
 export function buildSelectors<
-  InternalQueryArgs,
   Definitions extends EndpointDefinitions,
   ReducerPath extends string
 >({
   serializeQueryArgs,
   reducerPath,
 }: {
-  serializeQueryArgs: InternalSerializeQueryArgs<InternalQueryArgs>
+  serializeQueryArgs: InternalSerializeQueryArgs
   reducerPath: ReducerPath
 }) {
   type RootState = _RootState<Definitions, string, string>
diff --git a/src/query/core/buildSlice.ts b/src/query/core/buildSlice.ts
index a910e94f..19173357 100644
--- a/src/query/core/buildSlice.ts
+++ b/src/query/core/buildSlice.ts
@@ -78,8 +78,8 @@ export function buildSlice({
   config,
 }: {
   reducerPath: string
-  queryThunk: AsyncThunk<ThunkResult, QueryThunkArg<any>, {}>
-  mutationThunk: AsyncThunk<ThunkResult, MutationThunkArg<any>, {}>
+  queryThunk: AsyncThunk<ThunkResult, QueryThunkArg, {}>
+  mutationThunk: AsyncThunk<ThunkResult, MutationThunkArg, {}>
   context: ApiContext<EndpointDefinitions>
   assertTagType: AssertTagTypes
   config: Omit<ConfigState<string>, 'online' | 'focused'>
diff --git a/src/query/core/buildThunks.ts b/src/query/core/buildThunks.ts
index 868eecdb..c477cb17 100644
--- a/src/query/core/buildThunks.ts
+++ b/src/query/core/buildThunks.ts
@@ -108,7 +108,7 @@ export interface Matchers<
   matchRejected: Matcher<RejectedAction<Thunk, Definition>>
 }
 
-export interface QueryThunkArg<_InternalQueryArgs>
+export interface QueryThunkArg
   extends QuerySubstateIdentifier,
     StartQueryActionCreatorOptions {
   originalArgs: unknown
@@ -116,7 +116,7 @@ export interface QueryThunkArg<_InternalQueryArgs>
   startedTimeStamp: number
 }
 
-export interface MutationThunkArg<_InternalQueryArgs> {
+export interface MutationThunkArg {
   originalArgs: unknown
   endpointName: string
   track?: boolean
@@ -128,8 +128,8 @@ export interface ThunkResult {
   result: unknown
 }
 
-export type QueryThunk = AsyncThunk<ThunkResult, QueryThunkArg<any>, {}>
-export type MutationThunk = AsyncThunk<ThunkResult, MutationThunkArg<any>, {}>
+export type QueryThunk = AsyncThunk<ThunkResult, QueryThunkArg, {}>
+export type MutationThunk = AsyncThunk<ThunkResult, MutationThunkArg, {}>
 
 function defaultTransformResponse(baseQueryReturnValue: unknown) {
   return baseQueryReturnValue
@@ -172,10 +172,9 @@ export function buildThunks<
   baseQuery: BaseQuery
   reducerPath: ReducerPath
   context: ApiContext<Definitions>
-  serializeQueryArgs: InternalSerializeQueryArgs<BaseQueryArg<BaseQuery>>
+  serializeQueryArgs: InternalSerializeQueryArgs
   api: Api<BaseQuery, EndpointDefinitions, ReducerPath, any>
 }) {
-  type InternalQueryArgs = BaseQueryArg<BaseQuery>
   type State = RootState<any, string, ReducerPath>
 
   const patchQueryResult: PatchQueryResultThunk<EndpointDefinitions, State> = (
@@ -236,7 +235,7 @@ export function buildThunks<
 
   const executeEndpoint: AsyncThunkPayloadCreator<
     ThunkResult,
-    QueryThunkArg<InternalQueryArgs> | MutationThunkArg<InternalQueryArgs>,
+    QueryThunkArg | MutationThunkArg,
     { state: RootState<any, string, ReducerPath> }
   > = async (arg, { signal, rejectWithValue, ...api }) => {
     const endpointDefinition = endpointDefinitions[arg.endpointName]
@@ -311,7 +310,7 @@ export function buildThunks<
 
   const queryThunk = createAsyncThunk<
     ThunkResult,
-    QueryThunkArg<InternalQueryArgs>,
+    QueryThunkArg,
     { state: RootState<any, string, ReducerPath> }
   >(`${reducerPath}/executeQuery`, executeEndpoint, {
     condition(arg, { getState }) {
@@ -346,7 +345,7 @@ export function buildThunks<
 
   const mutationThunk = createAsyncThunk<
     ThunkResult,
-    MutationThunkArg<InternalQueryArgs>,
+    MutationThunkArg,
     { state: RootState<any, string, ReducerPath> }
   >(`${reducerPath}/executeMutation`, executeEndpoint)
 
@@ -404,8 +403,8 @@ export function buildThunks<
 
   function buildMatchThunkActions<
     Thunk extends
-      | AsyncThunk<any, QueryThunkArg<any>, any>
-      | AsyncThunk<any, MutationThunkArg<any>, any>
+      | AsyncThunk<any, QueryThunkArg, any>
+      | AsyncThunk<any, MutationThunkArg, any>
   >(thunk: Thunk, endpointName: string) {
     return {
       matchPending: isAllOf(isPending(thunk), matchesEndpoint(endpointName)),
diff --git a/src/query/core/module.ts b/src/query/core/module.ts
index de468469..a2f40cf7 100644
--- a/src/query/core/module.ts
+++ b/src/query/core/module.ts
@@ -240,7 +240,7 @@ export const coreModule = (): Module<CoreModule> => ({
     },
     context
   ) {
-    assertCast<InternalSerializeQueryArgs<any>>(serializeQueryArgs)
+    assertCast<InternalSerializeQueryArgs>(serializeQueryArgs)
 
     const assertTagType: AssertTagTypes = (tag) => {
       if (
diff --git a/src/query/defaultSerializeQueryArgs.ts b/src/query/defaultSerializeQueryArgs.ts
index 10ea6d74..f7d4db58 100644
--- a/src/query/defaultSerializeQueryArgs.ts
+++ b/src/query/defaultSerializeQueryArgs.ts
@@ -1,24 +1,31 @@
 import { QueryCacheKey } from './core/apiState'
 import { EndpointDefinition } from './endpointDefinitions'
+import { isPlainObject } from '@reduxjs/toolkit'
 
 export const defaultSerializeQueryArgs: SerializeQueryArgs<any> = ({
   endpointName,
   queryArgs,
 }) => {
   // Sort the object keys before stringifying, to prevent useQuery({ a: 1, b: 2 }) having a different cache key than useQuery({ b: 2, a: 1 })
-  return `${endpointName}(${JSON.stringify(
-    queryArgs,
-    Object.keys(queryArgs || {}).sort()
+  return `${endpointName}(${JSON.stringify(queryArgs, (key, value) =>
+    isPlainObject(value)
+      ? Object.keys(value)
+          .sort()
+          .reduce<any>((acc, key) => {
+            acc[key] = (value as any)[key]
+            return acc
+          }, {})
+      : value
   )})`
 }
 
-export type SerializeQueryArgs<_InternalQueryArgs> = (_: {
-  queryArgs: any
+export type SerializeQueryArgs<QueryArgs> = (_: {
+  queryArgs: QueryArgs
   endpointDefinition: EndpointDefinition<any, any, any, any>
   endpointName: string
 }) => string
 
-export type InternalSerializeQueryArgs<_InternalQueryArgs> = (_: {
+export type InternalSerializeQueryArgs = (_: {
   queryArgs: any
   endpointDefinition: EndpointDefinition<any, any, any, any>
   endpointName: string
diff --git a/src/query/endpointDefinitions.ts b/src/query/endpointDefinitions.ts
index e2b807fd..5fe22182 100644
--- a/src/query/endpointDefinitions.ts
+++ b/src/query/endpointDefinitions.ts
@@ -80,7 +80,7 @@ export enum DefinitionType {
   mutation = 'mutation',
 }
 
-type GetResultDescriptionFn<
+export type GetResultDescriptionFn<
   TagTypes extends string,
   ResultType,
   QueryArg,
@@ -95,8 +95,8 @@ export type FullTagDescription<TagType> = {
   type: TagType
   id?: number | string
 }
-type TagDescription<TagType> = TagType | FullTagDescription<TagType>
-type ResultDescription<
+export type TagDescription<TagType> = TagType | FullTagDescription<TagType>
+export type ResultDescription<
   TagTypes extends string,
   ResultType,
   QueryArg,
diff --git a/src/query/index.ts b/src/query/index.ts
index 8780398e..6289b69c 100644
--- a/src/query/index.ts
+++ b/src/query/index.ts
@@ -20,5 +20,5 @@ export { skipSelector } from './core/buildSelectors'
 export type { CreateApi, CreateApiOptions } from './createApi'
 export { buildCreateApi } from './createApi'
 export { fakeBaseQuery } from './fakeBaseQuery'
-
+export { copyWithStructuralSharing } from './utils/copyWithStructuralSharing'
 export { createApi, coreModule } from './core'
diff --git a/src/query/react/buildHooks.ts b/src/query/react/buildHooks.ts
index 51c7c34e..8fd65d3b 100644
--- a/src/query/react/buildHooks.ts
+++ b/src/query/react/buildHooks.ts
@@ -58,7 +58,19 @@ export interface MutationHooks<
 }
 
 /**
- * test description here
+ * A React hook that automatically triggers fetches of data from an endpoint, 'subscribes' the component to the cached data, and reads the request status and cached data from the Redux store. The component will re-render as the loading status changes and the data becomes available.
+ *
+ * The query arg is used as a cache key. Changing the query arg will tell the hook to re-fetch the data if it does not exist in the cache already, and the hook will return the data for that query arg once it's available.
+ *
+ * This hook combines the functionality of both [`useQueryState`](#usequerystate) and [`useQuerySubscription`](#usequerysubscription) together, and is intended to be used in the majority of situations.
+ *
+ * #### Features
+ *
+ * - Automatically triggers requests to retrieve data based on the hook argument and whether cached data exists by default
+ * - 'Subscribes' the component to keep cached data in the store, and 'unsubscribes' when the component unmounts
+ * - Accepts polling/re-fetching options to trigger automatic re-fetches when the corresponding criteria is met
+ * - Returns the latest request status and cached data from the Redux store
+ * - Re-renders as the request status changes and data becomes available
  */
 export type UseQuery<D extends QueryDefinition<any, any, any, any>> = <
   R extends Record<string, any> = UseQueryStateDefaultResult<D>
@@ -112,6 +124,19 @@ interface UseQuerySubscriptionOptions extends SubscriptionOptions {
   refetchOnMountOrArgChange?: boolean | number
 }
 
+/**
+ * A React hook that automatically triggers fetches of data from an endpoint, and 'subscribes' the component to the cached data.
+ *
+ * The query arg is used as a cache key. Changing the query arg will tell the hook to re-fetch the data if it does not exist in the cache already.
+ *
+ * Note that this hook does not return a request status or cached data. For that use-case, see [`useQuery`](#usequery) or [`useQueryState`](#usequerystate).
+ *
+ * #### Features
+ *
+ * - Automatically triggers requests to retrieve data based on the hook argument and whether cached data exists by default
+ * - 'Subscribes' the component to keep cached data in the store, and 'unsubscribes' when the component unmounts
+ * - Accepts polling/re-fetching options to trigger automatic re-fetches when the corresponding criteria is met
+ */
 export type UseQuerySubscription<
   D extends QueryDefinition<any, any, any, any>
 > = (
@@ -124,6 +149,21 @@ export type UseLazyQueryLastPromiseInfo<
 > = {
   lastArg: QueryArgFrom<D>
 }
+
+/**
+ * A React hook similar to [`useQuery`](#usequery), but with manual control over when the data fetching occurs.
+ *
+ * This hook includes the functionality of [`useLazyQuerySubscription`](#uselazyquerysubscription).
+ *
+ * #### Features
+ *
+ * - Manual control over firing a request to retrieve data
+ * - 'Subscribes' the component to keep cached data in the store, and 'unsubscribes' when the component unmounts
+ * - Returns the latest request status and cached data from the Redux store
+ * - Re-renders as the request status changes and data becomes available
+ * - Accepts polling/re-fetching options to trigger automatic re-fetches when the corresponding criteria is met and the fetch has been manually called at least once
+ *
+ */
 export type UseLazyQuery<D extends QueryDefinition<any, any, any, any>> = <
   R = UseQueryStateDefaultResult<D>
 >(
@@ -134,6 +174,17 @@ export type UseLazyQuery<D extends QueryDefinition<any, any, any, any>> = <
   UseLazyQueryLastPromiseInfo<D>
 ]
 
+/**
+ * A React hook similar to [`useQuerySubscription`](#usequerysubscription), but with manual control over when the data fetching occurs.
+ *
+ * Note that this hook does not return a request status or cached data. For that use-case, see [`useLazyQuery`](#uselazyquery).
+ *
+ * #### Features
+ *
+ * - Manual control over firing a request to retrieve data
+ * - 'Subscribes' the component to keep cached data in the store, and 'unsubscribes' when the component unmounts
+ * - Accepts polling/re-fetching options to trigger automatic re-fetches when the corresponding criteria is met and the fetch has been manually called at least once
+ */
 export type UseLazyQuerySubscription<
   D extends QueryDefinition<any, any, any, any>
 > = (
@@ -156,6 +207,16 @@ export type DefaultQueryStateSelector<
   lastResult: Pick<UseQueryStateDefaultResult<D>, 'data'>
 ) => UseQueryStateDefaultResult<D>
 
+/**
+ * A React hook that reads the request status and cached data from the Redux store. The component will re-render as the loading status changes and the data becomes available.
+ *
+ * Note that this hook does not trigger fetching new data. For that use-case, see [`useQuery`](#usequery) or [`useQuerySubscription`](#usequerysubscription).
+ *
+ * #### Features
+ *
+ * - Returns the latest request status and cached data from the Redux store
+ * - Re-renders as the request status changes and data becomes available
+ */
 export type UseQueryState<D extends QueryDefinition<any, any, any, any>> = <
   R = UseQueryStateDefaultResult<D>
 >(
@@ -316,6 +377,16 @@ export type UseMutationStateResult<
   R
 > = NoInfer<R>
 
+/**
+ * A React hook that lets you trigger an update request for a given endpoint, and subscribes the component to read the request status from the Redux store. The component will re-render as the loading status changes.
+ *
+ * #### Features
+ *
+ * - Manual control over firing a request to alter data on the server or possibly invalidate the cache
+ * - 'Subscribes' the component to keep cached data in the store, and 'unsubscribes' when the component unmounts
+ * - Returns the latest request status and cached data from the Redux store
+ * - Re-renders as the request status changes and data becomes available
+ */
 export type UseMutation<D extends MutationDefinition<any, any, any, any>> = <
   R extends Record<string, any> = MutationResultSelectorResult<D>
 >(
diff --git a/src/query/react/module.ts b/src/query/react/module.ts
index ed13a97c..b46d1ecb 100644
--- a/src/query/react/module.ts
+++ b/src/query/react/module.ts
@@ -12,7 +12,7 @@ import { capitalize } from '../utils'
 import { safeAssign } from '../tsHelpers'
 import { BaseQueryFn } from '../baseQueryTypes'
 
-import { HooksWithUniqueNames } from './versionedTypes/index'
+import { HooksWithUniqueNames } from './versionedTypes'
 
 import {
   useDispatch as rrUseDispatch,
diff --git a/src/query/react/versionedTypes/package.dist.json b/src/query/react/versionedTypes/package.dist.json
new file mode 100644
index 00000000..3e11bf7b
--- /dev/null
+++ b/src/query/react/versionedTypes/package.dist.json
@@ -0,0 +1,10 @@
+{
+  "typesVersions": {
+    ">=4.1": {
+      "index": ["./ts41Types.d.ts"]
+    },
+    "<4.1": {
+      "index": ["./ts40Types.d.ts"]
+    }
+  }
+}
diff --git a/src/query/react/versionedTypes/package.json b/src/query/react/versionedTypes/package.json
deleted file mode 100644
index 978648c7..00000000
--- a/src/query/react/versionedTypes/package.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "typesVersions": {
-    ">=4.1": {
-      "index": [
-        "./ts41Types.d.ts"
-      ]
-    },
-    "<4.1": {
-      "index": [
-        "./ts40Types.d.ts"
-      ]
-    }
-  }
-}
diff --git a/tsconfig.base.json b/tsconfig.base.json
index 28ee3547..09cbbdf4 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -31,9 +31,13 @@
     "emitDeclarationOnly": true,
     "baseUrl": ".",
     "paths": {
-      "@reduxjs/toolkit": ["src/index.ts"],
-      "@reduxjs/toolkit/query": ["src/query/index.ts"],
-      "@reduxjs/toolkit/query/react": ["src/query/react/index.ts"],
+      "@reduxjs/toolkit": ["src/index.ts"], // @remap-prod-remove-line
+      "@reduxjs/toolkit/query": ["src/query/index.ts"], // @remap-prod-remove-line
+      "@reduxjs/toolkit/query/react": ["src/query/react/index.ts"], // @remap-prod-remove-line
+      // for type imports in tests only
+      "@reduxjs/toolkit/dist/query/*": ["src/query/*"], // @remap-prod-remove-line
+      // internal imports in tests only
+      "@internal/*": ["src/*"]
     }
   }
-}
\ No newline at end of file
+}


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index d3f8bb39..3c4e24f5 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -33,7 +33,42 @@ jobs:
           name: package
           path: reduxjs-toolkit*.tgz
 
-  test:
+  test-dist:
+    name: Test against dist
+    needs: [build]
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        node: ['14.x']
+    steps:
+      - name: Checkout repo
+        uses: actions/checkout@v2
+
+      - name: Use node ${{ matrix.node }}
+        uses: actions/setup-node@v1
+        with:
+          node-version: ${{ matrix.node }}
+
+      - uses: c-hive/gha-npm-cache@v1
+
+      - name: Install deps
+        run: npm ci --ignore-scripts
+
+      - uses: actions/download-artifact@v2
+        with:
+          name: package
+
+      - name: Install build artifact
+        run: |
+          sed -i -e '/"name": "@reduxjs\/toolkit",/d' package.json
+          npm i reduxjs-toolkit-*.tgz --ignore-scripts
+          sed -i -e /@remap-prod-remove-line/d ./tsconfig.base.json ./jest.config.js ./src/tests/*.* ./src/query/tests/*.*
+
+      - name: Run tests, against dist
+        run: npm test
+
+  test-types:
     name: Test Types with TypeScript ${{ matrix.ts }}
 
     needs: [build]
@@ -42,7 +77,7 @@ jobs:
       fail-fast: false
       matrix:
         node: ['14.x']
-        ts: ['3.8', '3.9', '4.0', '4.1', 'next']
+        ts: ['3.9', '4.0', '4.1', '4.2', 'next']
     steps:
       - name: Checkout repo
         uses: actions/checkout@v2
@@ -64,26 +99,15 @@ jobs:
         with:
           name: package
 
-      - name: Unpack build artifact to dist
-        run: tar -xzvf reduxjs-toolkit-*.tgz --strip-components=1 package/dist
-
-      - name: Remap @redux/toolkit from src to dist
+      - name: Install build artifact
         run: |
-          sed -i -e 's|@reduxjs/toolkit": \["./src"\]|@reduxjs/toolkit": ["."]|' ./type-tests/files/tsconfig.json
+          sed -i -e '/"name": "@reduxjs\/toolkit",/d' package.json
+          npm i reduxjs-toolkit-*.tgz --ignore-scripts
+          sed -i -e /@remap-prod-remove-line/d ./tsconfig.base.json ./jest.config.js ./src/tests/*.* ./src/query/tests/*.*
 
-      - name: Prefix `freeze` re-export for pre-3.7 TS versions with @ts-ignore
-        if: ${{ matrix.ts < 3.7 }}
-        run: |
-          sed -i -e "/import .* freeze .* from 'immer'/s/^/\/\/ @ts-ignore\n/" dist/typings.d.ts
-          sed -i -e "/  freeze,/s/^/  \/\/ @ts-ignore\n/" src/index.ts
-
-      - name: Use typings-tester for old TS versions
-        if: ${{ matrix.ts < 3.9 }}
-        run: |
-          sed -i -e 's/"cd type-tests.*"/"npm run test type-tests"/' package.json
-          sed -i -e 's/@ts-expect-error/typings:expect-error/' type-tests/files/*.typetest.ts
-          sed -i -e 's/@ts-expect-error/@ts-ignore/' type-tests/files/*.ts
-          mv type-tests/types.test.disabled.ts type-tests/types.test.ts
+      - name: "@ts-ignore stuff that didn't exist pre-4.1 in the tests"
+        if: ${{ matrix.ts < 4.1 }}
+        run: sed -i -e 's/@pre41-ts-ignore/@ts-ignore/' -e  '/pre41-remove-start/,/pre41-remove-end/d' ./src/tests/*.* ./src/query/tests/*.ts*
 
       - name: Test types
         run: |
diff --git a/src/query/tests/apiProvider.test.tsx b/src/query/tests/apiProvider.test.tsx
index 09c1b548..80ed29b3 100644
--- a/src/query/tests/apiProvider.test.tsx
+++ b/src/query/tests/apiProvider.test.tsx
@@ -1,5 +1,5 @@
 import * as React from 'react'
-import { createApi, ApiProvider } from '../react'
+import { createApi, ApiProvider } from '@reduxjs/toolkit/query/react'
 import { fireEvent, render, waitFor } from '@testing-library/react'
 import { waitMs } from './helpers'
 
diff --git a/src/query/tests/buildHooks.test.tsx b/src/query/tests/buildHooks.test.tsx
index 5c5cc69a..e3395dcc 100644
--- a/src/query/tests/buildHooks.test.tsx
+++ b/src/query/tests/buildHooks.test.tsx
@@ -1,5 +1,9 @@
 import * as React from 'react'
-import { createApi, fetchBaseQuery, QueryStatus } from '../react'
+import {
+  createApi,
+  fetchBaseQuery,
+  QueryStatus,
+} from '@reduxjs/toolkit/query/react'
 import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
 import userEvent from '@testing-library/user-event'
 import { rest } from 'msw'
@@ -14,8 +18,8 @@ import {
 } from './helpers'
 import { server } from './mocks/server'
 import { AnyAction } from 'redux'
-import { SubscriptionOptions } from '../core/apiState'
-import { SerializedError } from '../../createAsyncThunk'
+import type { SubscriptionOptions } from '@reduxjs/toolkit/dist/query/core/apiState'
+import { SerializedError } from '@reduxjs/toolkit'
 
 // Just setup a temporary in-memory counter for tests that `getIncrementedAmount`.
 // This can be used to test how many renders happen due to data changes or
@@ -1518,6 +1522,7 @@ describe('hooks with createApi defaults set', () => {
     expectExactType(api.useGetPostsQuery)(api.endpoints.getPosts.useQuery)
     // @pre41-ts-ignore
     expectExactType(api.useUpdatePostMutation)(
+      // @pre41-ts-ignore
       api.endpoints.updatePost.useMutation
     )
     // @pre41-ts-ignore
diff --git a/src/query/tests/buildMiddleware.test.tsx b/src/query/tests/buildMiddleware.test.tsx
index 4d090e2b..d1bbed99 100644
--- a/src/query/tests/buildMiddleware.test.tsx
+++ b/src/query/tests/buildMiddleware.test.tsx
@@ -1,4 +1,4 @@
-import { createApi } from '../react'
+import { createApi } from '@reduxjs/toolkit/query'
 import { actionsReducer, matchSequence, setupApiStore, waitMs } from './helpers'
 
 const baseQuery = (args?: any) => ({ data: args })
diff --git a/src/query/tests/buildSlice.test.ts b/src/query/tests/buildSlice.test.ts
index 798b30aa..e3a4a775 100644
--- a/src/query/tests/buildSlice.test.ts
+++ b/src/query/tests/buildSlice.test.ts
@@ -1,5 +1,5 @@
-import { createSlice } from '../..'
-import { createApi } from '../react'
+import { createSlice } from '@reduxjs/toolkit'
+import { createApi } from '@reduxjs/toolkit/query'
 import { setupApiStore } from './helpers'
 
 const baseQuery = (args?: any) => ({ data: args })
diff --git a/src/query/tests/buildThunks.test.tsx b/src/query/tests/buildThunks.test.tsx
index 56eff9b4..8919807e 100644
--- a/src/query/tests/buildThunks.test.tsx
+++ b/src/query/tests/buildThunks.test.tsx
@@ -1,5 +1,5 @@
-import { configureStore } from '../../' // '@reduxjs/toolkit'
-import { createApi } from '../react'
+import { configureStore } from '@reduxjs/toolkit'
+import { createApi } from '@reduxjs/toolkit/query/react'
 
 import { renderHook } from '@testing-library/react-hooks'
 import { withProvider } from './helpers'
diff --git a/src/query/tests/cleanup.test.tsx b/src/query/tests/cleanup.test.tsx
index 977edda2..1b96d723 100644
--- a/src/query/tests/cleanup.test.tsx
+++ b/src/query/tests/cleanup.test.tsx
@@ -2,7 +2,7 @@
 
 import React from 'react'
 
-import { createApi, QueryStatus } from '../react'
+import { createApi, QueryStatus } from '@reduxjs/toolkit/query/react'
 import { render, waitFor } from '@testing-library/react'
 import { setupApiStore } from './helpers'
 
diff --git a/src/query/tests/copyWithStructuralSharing.test.ts b/src/query/tests/copyWithStructuralSharing.test.ts
index ded93f9a..889414d9 100644
--- a/src/query/tests/copyWithStructuralSharing.test.ts
+++ b/src/query/tests/copyWithStructuralSharing.test.ts
@@ -1,4 +1,4 @@
-import { copyWithStructuralSharing } from '../utils/copyWithStructuralSharing'
+import { copyWithStructuralSharing } from '@reduxjs/toolkit/query'
 
 test('equal object from JSON Object', () => {
   const json = JSON.stringify({
diff --git a/src/query/tests/createApi.test.ts b/src/query/tests/createApi.test.ts
index 74a522a3..8ae5524e 100644
--- a/src/query/tests/createApi.test.ts
+++ b/src/query/tests/createApi.test.ts
@@ -1,6 +1,11 @@
-import { configureStore, createAction, createReducer } from '../..'
-import { Api, createApi, fetchBaseQuery } from '..'
-import { QueryDefinition, MutationDefinition } from '../endpointDefinitions'
+import { configureStore, createAction, createReducer } from '@reduxjs/toolkit'
+import {
+  Api,
+  createApi,
+  fetchBaseQuery,
+  MutationDefinition,
+  QueryDefinition,
+} from '@reduxjs/toolkit/query'
 import {
   ANY,
   expectType,
diff --git a/src/query/tests/defaultSerializeQueryArgs.test.ts b/src/query/tests/defaultSerializeQueryArgs.test.ts
new file mode 100644
index 00000000..02040228
--- /dev/null
+++ b/src/query/tests/defaultSerializeQueryArgs.test.ts
@@ -0,0 +1,46 @@
+import { defaultSerializeQueryArgs } from '@internal/query/defaultSerializeQueryArgs'
+
+const endpointDefinition: any = {}
+const endpointName = 'test'
+
+test('string arg', () => {
+  expect(
+    defaultSerializeQueryArgs({
+      endpointDefinition,
+      endpointName,
+      queryArgs: 'arg',
+    })
+  ).toMatchInlineSnapshot(`"test(\\"arg\\")"`)
+})
+
+test('number arg', () => {
+  expect(
+    defaultSerializeQueryArgs({
+      endpointDefinition,
+      endpointName,
+      queryArgs: 5,
+    })
+  ).toMatchInlineSnapshot(`"test(5)"`)
+})
+
+test('simple object arg is sorted', () => {
+  expect(
+    defaultSerializeQueryArgs({
+      endpointDefinition,
+      endpointName,
+      queryArgs: { name: 'arg', age: 5 },
+    })
+  ).toMatchInlineSnapshot(`"test({\\"age\\":5,\\"name\\":\\"arg\\"})"`)
+})
+
+test('nested object arg is sorted recursively', () => {
+  expect(
+    defaultSerializeQueryArgs({
+      endpointDefinition,
+      endpointName,
+      queryArgs: { name: { last: 'Split', first: 'Banana' }, age: 5 },
+    })
+  ).toMatchInlineSnapshot(
+    `"test({\\"age\\":5,\\"name\\":{\\"first\\":\\"Banana\\",\\"last\\":\\"Split\\"}})"`
+  )
+})
diff --git a/src/query/tests/errorHandling.test.tsx b/src/query/tests/errorHandling.test.tsx
index ffdfd7c4..c40e395f 100644
--- a/src/query/tests/errorHandling.test.tsx
+++ b/src/query/tests/errorHandling.test.tsx
@@ -1,5 +1,9 @@
 import * as React from 'react'
-import { BaseQueryFn, createApi, fetchBaseQuery } from '../react'
+import {
+  BaseQueryFn,
+  createApi,
+  fetchBaseQuery,
+} from '@reduxjs/toolkit/query/react'
 import { renderHook, act } from '@testing-library/react-hooks'
 import { rest } from 'msw'
 import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
@@ -8,7 +12,7 @@ import { expectExactType, hookWaitFor, setupApiStore } from './helpers'
 import { server } from './mocks/server'
 import { fireEvent, render, waitFor, screen } from '@testing-library/react'
 import { useDispatch } from 'react-redux'
-import { AnyAction, ThunkDispatch } from '../..'
+import { AnyAction, ThunkDispatch } from '@reduxjs/toolkit'
 
 const baseQuery = fetchBaseQuery({ baseUrl: 'http://example.com' })
 
diff --git a/src/query/tests/fakeBaseQuery.test.tsx b/src/query/tests/fakeBaseQuery.test.tsx
index d5c3bd85..5b097806 100644
--- a/src/query/tests/fakeBaseQuery.test.tsx
+++ b/src/query/tests/fakeBaseQuery.test.tsx
@@ -1,5 +1,5 @@
-import { configureStore } from '../../configureStore'
-import { createApi, fakeBaseQuery } from '..'
+import { configureStore } from '@reduxjs/toolkit'
+import { createApi, fakeBaseQuery } from '@reduxjs/toolkit/query'
 
 type CustomErrorType = { type: 'Custom' }
 
diff --git a/src/query/tests/fetchBaseQuery.test.tsx b/src/query/tests/fetchBaseQuery.test.tsx
index 83131388..7bda199f 100644
--- a/src/query/tests/fetchBaseQuery.test.tsx
+++ b/src/query/tests/fetchBaseQuery.test.tsx
@@ -1,5 +1,5 @@
-import { createSlice } from '../../'
-import { createApi, fetchBaseQuery } from '..'
+import { createSlice } from '@reduxjs/toolkit'
+import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
 import { setupApiStore } from './helpers'
 import { default as crossFetch } from 'cross-fetch'
 
diff --git a/src/query/tests/helpers.tsx b/src/query/tests/helpers.tsx
index 629ee7a1..5330e36f 100644
--- a/src/query/tests/helpers.tsx
+++ b/src/query/tests/helpers.tsx
@@ -4,8 +4,8 @@ import {
   EnhancedStore,
   Middleware,
   Store,
-} from '../../'
-import { setupListeners } from '..'
+} from '@reduxjs/toolkit'
+import { setupListeners } from '@reduxjs/toolkit/query'
 
 import { act } from '@testing-library/react-hooks'
 import React, { Reducer, useCallback } from 'react'
@@ -109,6 +109,7 @@ export function setupApiStore<
     reducerPath: any
     reducer: Reducer<any, any>
     middleware: Middleware<any>
+    util: { resetApiState(): any }
   },
   R extends Record<string, Reducer<any, any>>
 >(api: A, extraReducers?: R, withoutListeners?: boolean) {
@@ -157,6 +158,7 @@ export function setupApiStore<
     if (!withoutListeners) {
       cleanupListeners()
     }
+    refObj.store.dispatch(api.util.resetApiState())
   })
 
   return refObj
diff --git a/src/query/tests/invalidation.test.tsx b/src/query/tests/invalidation.test.tsx
new file mode 100644
index 00000000..afcd052e
--- /dev/null
+++ b/src/query/tests/invalidation.test.tsx
@@ -0,0 +1,97 @@
+import { createApi, fakeBaseQuery } from '@reduxjs/toolkit/query'
+import { setupApiStore, waitMs } from './helpers'
+import type { ResultDescription } from '@reduxjs/toolkit/dist/query/endpointDefinitions'
+
+const tagTypes = ['apple', 'pear', 'banana', 'tomato'] as const
+type TagTypes = typeof tagTypes[number]
+type Tags = ResultDescription<TagTypes, any, any, any>
+
+/** providesTags, invalidatesTags, shouldInvalidate */
+const caseMatrix: [Tags, Tags, boolean][] = [
+  // *****************************
+  // basic invalidation behaviour
+  // *****************************
+
+  // string
+  [['apple'], ['apple'], true],
+  [['apple'], ['pear'], false],
+  // string and type only behave identical
+  [[{ type: 'apple' }], ['apple'], true],
+  [[{ type: 'apple' }], ['pear'], false],
+  [['apple'], [{ type: 'apple' }], true],
+  [['apple'], [{ type: 'pear' }], false],
+  // type only invalidates type + id
+  [[{ type: 'apple', id: 1 }], [{ type: 'apple' }], true],
+  [[{ type: 'pear', id: 1 }], ['apple'], false],
+  // type + id never invalidates type only
+  [['apple'], [{ type: 'apple', id: 1 }], false],
+  [['pear'], [{ type: 'apple', id: 1 }], false],
+  // type + id invalidates type + id
+  [[{ type: 'apple', id: 1 }], [{ type: 'apple', id: 1 }], true],
+  [[{ type: 'apple', id: 1 }], [{ type: 'apple', id: 2 }], false],
+
+  // *****************************
+  // test multiple values in array
+  // *****************************
+
+  [['apple', 'banana', 'tomato'], ['apple'], true],
+  [['apple'], ['pear', 'banana', 'tomato'], false],
+  [
+    [
+      { type: 'apple', id: 1 },
+      { type: 'apple', id: 3 },
+      { type: 'apple', id: 4 },
+    ],
+    [{ type: 'apple', id: 1 }],
+    true,
+  ],
+  [
+    [{ type: 'apple', id: 1 }],
+    [
+      { type: 'apple', id: 2 },
+      { type: 'apple', id: 3 },
+      { type: 'apple', id: 4 },
+    ],
+    false,
+  ],
+]
+
+test.each(caseMatrix)(
+  '\tprovidesTags: %O,\n\tinvalidatesTags: %O,\n\tshould invalidate: %s',
+  async (providesTags, invalidatesTags, shouldInvalidate) => {
+    let queryCount = 0
+    const {
+      store,
+      api: {
+        endpoints: { invalidating, providing },
+      },
+    } = setupApiStore(
+      createApi({
+        baseQuery: fakeBaseQuery(),
+        tagTypes,
+        endpoints: (build) => ({
+          providing: build.query<unknown, void>({
+            queryFn() {
+              queryCount++
+              return { data: {} }
+            },
+            providesTags,
+          }),
+          invalidating: build.mutation<unknown, void>({
+            queryFn() {
+              return { data: {} }
+            },
+            invalidatesTags,
+          }),
+        }),
+      })
+    )
+
+    store.dispatch(providing.initiate())
+    expect(queryCount).toBe(1)
+    store.dispatch(invalidating.initiate())
+    expect(queryCount).toBe(1)
+    await waitMs(2)
+    expect(queryCount).toBe(shouldInvalidate ? 2 : 1)
+  }
+)
diff --git a/src/query/tests/matchers.test.tsx b/src/query/tests/matchers.test.tsx
index 62fc15b7..848079dd 100644
--- a/src/query/tests/matchers.test.tsx
+++ b/src/query/tests/matchers.test.tsx
@@ -1,5 +1,5 @@
-import { createSlice, SerializedError } from '../../'
-import { createApi, fetchBaseQuery } from '../react'
+import { createSlice, SerializedError } from '@reduxjs/toolkit'
+import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
 import { renderHook, act } from '@testing-library/react-hooks'
 import {
   actionsReducer,
diff --git a/src/query/tests/optimisticUpdates.test.tsx b/src/query/tests/optimisticUpdates.test.tsx
index da2bbe74..ed0c72e5 100644
--- a/src/query/tests/optimisticUpdates.test.tsx
+++ b/src/query/tests/optimisticUpdates.test.tsx
@@ -1,4 +1,4 @@
-import { createApi } from '../react'
+import { createApi } from '@reduxjs/toolkit/query/react'
 import { actionsReducer, hookWaitFor, setupApiStore, waitMs } from './helpers'
 import { renderHook, act } from '@testing-library/react-hooks'
 
diff --git a/src/query/tests/queryFn.test.tsx b/src/query/tests/queryFn.test.tsx
index 1d4a7326..10950224 100644
--- a/src/query/tests/queryFn.test.tsx
+++ b/src/query/tests/queryFn.test.tsx
@@ -1,5 +1,10 @@
-import { configureStore } from '../../'
-import { BaseQueryFn, createApi, fetchBaseQuery, FetchBaseQueryError } from '..'
+import { configureStore } from '@reduxjs/toolkit'
+import {
+  BaseQueryFn,
+  createApi,
+  fetchBaseQuery,
+  FetchBaseQueryError,
+} from '@reduxjs/toolkit/query'
 import { Post, posts } from './mocks/server'
 import { actionsReducer, setupApiStore } from './helpers'
 
@@ -262,11 +267,11 @@ describe('usage scenario tests', () => {
     exists: () => true,
     data: () => mockData,
   }
-  const collection = jest.fn((name) => ({ get, doc }))
   const get = jest.fn(() => Promise.resolve(mockDocResult))
   const doc = jest.fn((name) => ({
     get,
   }))
+  const collection = jest.fn((name) => ({ get, doc }))
   const firestore = () => {
     return { collection, doc }
   }
diff --git a/src/query/tests/refetchingBehaviors.test.tsx b/src/query/tests/refetchingBehaviors.test.tsx
index f4a84a4d..50b908a4 100644
--- a/src/query/tests/refetchingBehaviors.test.tsx
+++ b/src/query/tests/refetchingBehaviors.test.tsx
@@ -1,8 +1,8 @@
 import * as React from 'react'
-import { createApi, setupListeners } from '../react'
+import { createApi, setupListeners } from '@reduxjs/toolkit/query/react'
 import { act, fireEvent, render, waitFor, screen } from '@testing-library/react'
 import { setupApiStore, waitMs } from './helpers'
-import { AnyAction } from '../..'
+import { AnyAction } from '@reduxjs/toolkit'
 
 // Just setup a temporary in-memory counter for tests that `getIncrementedAmount`.
 // This can be used to test how many renders happen due to data changes or
diff --git a/src/query/tests/retry.test.ts b/src/query/tests/retry.test.ts
index 920e7799..bc2acf2f 100644
--- a/src/query/tests/retry.test.ts
+++ b/src/query/tests/retry.test.ts
@@ -1,4 +1,4 @@
-import { BaseQueryFn, createApi, retry } from '..'
+import { BaseQueryFn, createApi, retry } from '@reduxjs/toolkit/query'
 import { setupApiStore, waitMs } from './helpers'
 
 beforeEach(() => {
diff --git a/src/query/tests/tsconfig.json b/src/query/tests/tsconfig.json
new file mode 100644
index 00000000..105334e2
--- /dev/null
+++ b/src/query/tests/tsconfig.json
@@ -0,0 +1,3 @@
+{
+  "extends": "../../../tsconfig.test.json"
+}
diff --git a/src/query/tests/unionTypes.test.ts b/src/query/tests/unionTypes.test.ts
index 39cb88f4..95d4692e 100644
--- a/src/query/tests/unionTypes.test.ts
+++ b/src/query/tests/unionTypes.test.ts
@@ -1,5 +1,9 @@
-import { SerializedError } from '../..'
-import { createApi, fetchBaseQuery, FetchBaseQueryError } from '../react'
+import { SerializedError } from '@reduxjs/toolkit'
+import {
+  createApi,
+  fetchBaseQuery,
+  FetchBaseQueryError,
+} from '@reduxjs/toolkit/query/react'
 import { expectExactType, expectType } from './helpers'
 
 const api = createApi({
diff --git a/src/query/tests/utils.test.ts b/src/query/tests/utils.test.ts
index 89011d7b..4b111b2a 100644
--- a/src/query/tests/utils.test.ts
+++ b/src/query/tests/utils.test.ts
@@ -1,4 +1,9 @@
-import { isOnline, isDocumentVisible, flatten, joinUrls } from '../utils'
+import {
+  isOnline,
+  isDocumentVisible,
+  flatten,
+  joinUrls,
+} from '@internal/query/utils'
 
 afterAll(() => {
   jest.restoreAllMocks()
diff --git a/type-tests/files/MiddlewareArray.typetest.ts b/src/tests/MiddlewareArray.typetest.ts
similarity index 98%
rename from type-tests/files/MiddlewareArray.typetest.ts
rename to src/tests/MiddlewareArray.typetest.ts
index 468db08d..9bb090b9 100644
--- a/type-tests/files/MiddlewareArray.typetest.ts
+++ b/src/tests/MiddlewareArray.typetest.ts
@@ -49,7 +49,7 @@ declare const thunkCreator: () => () => ThunkReturn
   {
     const concatenated = defaultMiddleware.prepend([
       middleware1,
-      middleware2
+      middleware2,
     ] as const)
     const dispatch = getDispatch(concatenated)
     expectType<number>(dispatch('foo'))
@@ -87,7 +87,7 @@ declare const thunkCreator: () => () => ThunkReturn
   {
     const concatenated = defaultMiddleware.concat([
       middleware1,
-      middleware2
+      middleware2,
     ] as const)
     const dispatch = getDispatch(concatenated)
     expectType<number>(dispatch('foo'))
diff --git a/src/tests/combinedTest.test.ts b/src/tests/combinedTest.test.ts
index 6b95423c..b210cbb3 100644
--- a/src/tests/combinedTest.test.ts
+++ b/src/tests/combinedTest.test.ts
@@ -1,10 +1,13 @@
-import { createAsyncThunk } from '../createAsyncThunk'
-import { createAction, PayloadAction } from '../createAction'
-import { createSlice } from '../createSlice'
-import { configureStore } from '../configureStore'
-import { createEntityAdapter } from '../entities/create_adapter'
-import { EntityAdapter } from '../entities/models'
-import { BookModel } from '../entities/tests/fixtures/book'
+import {
+  createAsyncThunk,
+  createAction,
+  PayloadAction,
+  createSlice,
+  configureStore,
+  createEntityAdapter,
+} from '@reduxjs/toolkit'
+import { EntityAdapter } from '@internal/entities/models'
+import { BookModel } from '@internal/entities/tests/fixtures/book'
 
 describe('Combined entity slice', () => {
   let adapter: EntityAdapter<BookModel>
diff --git a/src/tests/configureStore.test.ts b/src/tests/configureStore.test.ts
index ed1fca7a..15d18416 100644
--- a/src/tests/configureStore.test.ts
+++ b/src/tests/configureStore.test.ts
@@ -1,14 +1,18 @@
-import { configureStore } from '../configureStore'
+import {
+  configureStore,
+  StoreEnhancer,
+  StoreEnhancerStoreCreator,
+} from '@reduxjs/toolkit'
+import * as RTK from '@reduxjs/toolkit'
 import * as redux from 'redux'
-import * as devtools from '../devtoolsExtension'
-import { StoreEnhancer, StoreEnhancerStoreCreator } from 'redux'
+import * as devtools from '@internal/devtoolsExtension'
 
 describe('configureStore', () => {
   jest.spyOn(redux, 'applyMiddleware')
   jest.spyOn(redux, 'combineReducers')
   jest.spyOn(redux, 'compose')
   jest.spyOn(redux, 'createStore')
-  jest.spyOn(devtools, 'composeWithDevTools')
+  jest.spyOn(devtools, 'composeWithDevTools') // @remap-prod-remove-line
 
   const reducer: redux.Reducer = (state = {}, _action) => state
 
@@ -19,7 +23,7 @@ describe('configureStore', () => {
       configureStore({ reducer })
       expect(configureStore({ reducer })).toBeInstanceOf(Object)
       expect(redux.applyMiddleware).toHaveBeenCalled()
-      expect(devtools.composeWithDevTools).toHaveBeenCalled()
+      expect(devtools.composeWithDevTools).toHaveBeenCalled() // @remap-prod-remove-line
       expect(redux.createStore).toHaveBeenCalledWith(
         reducer,
         undefined,
@@ -38,7 +42,7 @@ describe('configureStore', () => {
       expect(configureStore({ reducer })).toBeInstanceOf(Object)
       expect(redux.combineReducers).toHaveBeenCalledWith(reducer)
       expect(redux.applyMiddleware).toHaveBeenCalled()
-      expect(devtools.composeWithDevTools).toHaveBeenCalled()
+      expect(devtools.composeWithDevTools).toHaveBeenCalled() // @remap-prod-remove-line-line
       expect(redux.createStore).toHaveBeenCalledWith(
         expect.any(Function),
         undefined,
@@ -59,7 +63,7 @@ describe('configureStore', () => {
     it('calls createStore without any middleware', () => {
       expect(configureStore({ middleware: [], reducer })).toBeInstanceOf(Object)
       expect(redux.applyMiddleware).toHaveBeenCalledWith()
-      expect(devtools.composeWithDevTools).toHaveBeenCalled()
+      expect(devtools.composeWithDevTools).toHaveBeenCalled() // @remap-prod-remove-line-line
       expect(redux.createStore).toHaveBeenCalledWith(
         reducer,
         undefined,
@@ -78,7 +82,7 @@ describe('configureStore', () => {
         expect.any(Function), // immutableCheck
         expect.any(Function) // serializableCheck
       )
-      expect(devtools.composeWithDevTools).toHaveBeenCalled()
+      expect(devtools.composeWithDevTools).toHaveBeenCalled() // @remap-prod-remove-line-line
       expect(redux.createStore).toHaveBeenCalledWith(
         reducer,
         undefined,
@@ -123,7 +127,7 @@ describe('configureStore', () => {
         Object
       )
       expect(redux.applyMiddleware).toHaveBeenCalledWith(thank)
-      expect(devtools.composeWithDevTools).toHaveBeenCalled()
+      expect(devtools.composeWithDevTools).toHaveBeenCalled() // @remap-prod-remove-line-line
       expect(redux.createStore).toHaveBeenCalledWith(
         reducer,
         undefined,
@@ -177,7 +181,7 @@ describe('configureStore', () => {
         Object
       )
       expect(redux.applyMiddleware).toHaveBeenCalled()
-      expect(devtools.composeWithDevTools).toHaveBeenCalledWith(options)
+      expect(devtools.composeWithDevTools).toHaveBeenCalledWith(options) // @remap-prod-remove-line
       expect(redux.createStore).toHaveBeenCalledWith(
         reducer,
         undefined,
@@ -190,7 +194,7 @@ describe('configureStore', () => {
     it('calls createStore with preloadedState', () => {
       expect(configureStore({ reducer })).toBeInstanceOf(Object)
       expect(redux.applyMiddleware).toHaveBeenCalled()
-      expect(devtools.composeWithDevTools).toHaveBeenCalled()
+      expect(devtools.composeWithDevTools).toHaveBeenCalled() // @remap-prod-remove-line
       expect(redux.createStore).toHaveBeenCalledWith(
         reducer,
         undefined,
@@ -206,7 +210,7 @@ describe('configureStore', () => {
         Object
       )
       expect(redux.applyMiddleware).toHaveBeenCalled()
-      expect(devtools.composeWithDevTools).toHaveBeenCalled()
+      expect(devtools.composeWithDevTools).toHaveBeenCalled() // @remap-prod-remove-line
       expect(redux.createStore).toHaveBeenCalledWith(
         reducer,
         undefined,
diff --git a/type-tests/files/configureStore.typetest.ts b/src/tests/configureStore.typetest.ts
similarity index 84%
rename from type-tests/files/configureStore.typetest.ts
rename to src/tests/configureStore.typetest.ts
index a36ecb35..ff9668a8 100644
--- a/type-tests/files/configureStore.typetest.ts
+++ b/src/tests/configureStore.typetest.ts
@@ -5,12 +5,12 @@ import {
   AnyAction,
   Middleware,
   Reducer,
-  Store
+  Store,
 } from 'redux'
 import {
   configureStore,
   PayloadAction,
-  getDefaultMiddleware
+  getDefaultMiddleware,
 } from '@reduxjs/toolkit'
 import thunk, { ThunkMiddleware, ThunkAction, ThunkDispatch } from 'redux-thunk'
 import { expectType } from './helpers'
@@ -22,14 +22,14 @@ const _anyMiddleware: any = () => () => () => {}
  */
 {
   configureStore({
-    reducer: (state, action) => 0
+    reducer: (state, action) => 0,
   })
 
   configureStore({
     reducer: {
       counter1: () => 0,
-      counter2: () => 1
-    }
+      counter2: () => 1,
+    },
   })
 
   // @ts-expect-error
@@ -70,17 +70,17 @@ const _anyMiddleware: any = () => () => () => {}
  * Test: configureStore() accepts middleware array.
  */
 {
-  const middleware: Middleware = store => next => next
+  const middleware: Middleware = (store) => (next) => next
 
   configureStore({
     reducer: () => 0,
-    middleware: [middleware]
+    middleware: [middleware],
   })
 
   configureStore({
     reducer: () => 0,
     // @ts-expect-error
-    middleware: ['not middleware']
+    middleware: ['not middleware'],
   })
 }
 
@@ -90,13 +90,13 @@ const _anyMiddleware: any = () => () => () => {}
 {
   configureStore({
     reducer: () => 0,
-    devTools: true
+    devTools: true,
   })
 
   configureStore({
     reducer: () => 0,
     // @ts-expect-error
-    devTools: 'true'
+    devTools: 'true',
   })
 }
 
@@ -106,13 +106,13 @@ const _anyMiddleware: any = () => () => () => {}
 {
   configureStore({
     reducer: () => 0,
-    devTools: { name: 'myApp' }
+    devTools: { name: 'myApp' },
   })
 
   configureStore({
     reducer: () => 0,
     // @ts-expect-error
-    devTools: { appname: 'myApp' }
+    devTools: { appname: 'myApp' },
   })
 }
 
@@ -122,13 +122,13 @@ const _anyMiddleware: any = () => () => () => {}
 {
   configureStore({
     reducer: () => 0,
-    preloadedState: 0
+    preloadedState: 0,
   })
 
   configureStore({
     reducer: () => 0,
     // @ts-expect-error
-    preloadedState: 'non-matching state type'
+    preloadedState: 'non-matching state type',
   })
 }
 
@@ -138,13 +138,13 @@ const _anyMiddleware: any = () => () => () => {}
 {
   configureStore({
     reducer: () => 0,
-    enhancers: [applyMiddleware(store => next => next)]
+    enhancers: [applyMiddleware((store) => (next) => next)],
   })
 
   configureStore({
     reducer: () => 0,
     // @ts-expect-error
-    enhancers: ['not a store enhancer']
+    enhancers: ['not a store enhancer'],
   })
 }
 
@@ -159,11 +159,11 @@ const _anyMiddleware: any = () => () => () => {}
   const store = configureStore({
     reducer: {
       counter1: counterReducer1,
-      counter2: counterReducer2
+      counter2: counterReducer2,
     },
     preloadedState: {
-      counter1: 0
-    }
+      counter1: 0,
+    },
   })
 
   const counter1: number = store.getState().counter1
@@ -189,7 +189,7 @@ const _anyMiddleware: any = () => () => () => {}
    */
   {
     const store = configureStore({
-      reducer: reducerA
+      reducer: reducerA,
     })
 
     store.dispatch(thunkA())
@@ -202,7 +202,7 @@ const _anyMiddleware: any = () => () => () => {}
   {
     const store = configureStore({
       reducer: reducerA,
-      middleware: []
+      middleware: [],
     })
     // @ts-expect-error
     store.dispatch(thunkA())
@@ -215,7 +215,7 @@ const _anyMiddleware: any = () => () => () => {}
   {
     const store = configureStore({
       reducer: reducerA,
-      middleware: [thunk] as [ThunkMiddleware<StateA>]
+      middleware: [thunk] as [ThunkMiddleware<StateA>],
     })
     store.dispatch(thunkA())
     // @ts-expect-error
@@ -227,7 +227,7 @@ const _anyMiddleware: any = () => () => () => {}
   {
     const store = configureStore({
       reducer: reducerA,
-      middleware: getDefaultMiddleware<StateA>()
+      middleware: getDefaultMiddleware<StateA>(),
     })
 
     store.dispatch(thunkA())
@@ -240,7 +240,7 @@ const _anyMiddleware: any = () => () => () => {}
   {
     const store = configureStore({
       reducer: reducerA,
-      middleware: ([] as any) as [Middleware<(a: StateA) => boolean, StateA>]
+      middleware: ([] as any) as [Middleware<(a: StateA) => boolean, StateA>],
     })
     const result: boolean = store.dispatch(5)
     // @ts-expect-error
@@ -256,7 +256,7 @@ const _anyMiddleware: any = () => () => () => {}
         Middleware<(a: 'a') => 'A', StateA>,
         Middleware<(b: 'b') => 'B', StateA>,
         ThunkMiddleware<StateA>
-      ]
+      ],
     })
     const result: 'A' = store.dispatch('a')
     const result2: 'B' = store.dispatch('b')
@@ -268,15 +268,20 @@ const _anyMiddleware: any = () => () => () => {}
   {
     const store = configureStore({ reducer: {} })
     // undefined is the default value for the ThunkMiddleware extraArgument
-    store.dispatch(function() {} as ThunkAction<void, {}, undefined, AnyAction>)
+    store.dispatch(function () {} as ThunkAction<
+      void,
+      {},
+      undefined,
+      AnyAction
+    >)
     // null was previously documented in the redux docs
-    store.dispatch(function() {} as ThunkAction<void, {}, null, AnyAction>)
+    store.dispatch(function () {} as ThunkAction<void, {}, null, AnyAction>)
     // unknown is the best way to type a ThunkAction if you do not care
     // about the value of the extraArgument, as it will always work with every
     // ThunkMiddleware, no matter the actual extraArgument type
-    store.dispatch(function() {} as ThunkAction<void, {}, unknown, AnyAction>)
+    store.dispatch(function () {} as ThunkAction<void, {}, unknown, AnyAction>)
     // @ts-expect-error
-    store.dispatch(function() {} as ThunkAction<void, {}, boolean, AnyAction>)
+    store.dispatch(function () {} as ThunkAction<void, {}, boolean, AnyAction>)
   }
 
   /**
@@ -287,8 +292,8 @@ const _anyMiddleware: any = () => () => () => {}
       reducer: reducerA,
       middleware: [
         ((() => {}) as any) as Middleware<(a: 'a') => 'A', StateA>,
-        ...getDefaultMiddleware<StateA>()
-      ] as const
+        ...getDefaultMiddleware<StateA>(),
+      ] as const,
     })
     const result1: 'A' = store.dispatch('a')
     const result2: Promise<'A'> = store.dispatch(thunkA())
@@ -309,7 +314,7 @@ const _anyMiddleware: any = () => () => () => {}
 
     const store = configureStore({
       reducer: reducerA,
-      middleware: concatenated
+      middleware: concatenated,
     })
     const result1: 'A' = store.dispatch('a')
     const result2: Promise<'A'> = store.dispatch(thunkA())
@@ -330,7 +335,7 @@ const _anyMiddleware: any = () => () => () => {}
 
     const store = configureStore({
       reducer: reducerA,
-      middleware: concatenated
+      middleware: concatenated,
     })
     const result1: 'A' = store.dispatch('a')
     const result2: Promise<'A'> = store.dispatch(thunkA())
@@ -344,11 +349,11 @@ const _anyMiddleware: any = () => () => () => {}
   {
     const store = configureStore({
       reducer: reducerA,
-      middleware: getDefaultMiddleware =>
+      middleware: (getDefaultMiddleware) =>
         [
           ((() => {}) as any) as Middleware<(a: 'a') => 'A', StateA>,
-          ...getDefaultMiddleware()
-        ] as const
+          ...getDefaultMiddleware(),
+        ] as const,
     })
     const result1: 'A' = store.dispatch('a')
     const result2: Promise<'A'> = store.dispatch(thunkA())
@@ -364,10 +369,10 @@ const _anyMiddleware: any = () => () => () => {}
     const otherMiddleware2: Middleware<(a: 'b') => 'B', StateA> = _anyMiddleware
     const store = configureStore({
       reducer: reducerA,
-      middleware: getDefaultMiddleware =>
+      middleware: (getDefaultMiddleware) =>
         getDefaultMiddleware()
           .concat(otherMiddleware)
-          .prepend(otherMiddleware2)
+          .prepend(otherMiddleware2),
     })
     const result1: 'A' = store.dispatch('a')
     const result2: Promise<'A'> = store.dispatch(thunkA())
@@ -382,11 +387,11 @@ const _anyMiddleware: any = () => () => () => {}
   {
     const store = configureStore({
       reducer: reducerA,
-      middleware: getDefaultMiddleware =>
+      middleware: (getDefaultMiddleware) =>
         [
           ((() => {}) as any) as Middleware<(a: 'a') => 'A', StateA>,
-          ...getDefaultMiddleware({ thunk: false })
-        ] as const
+          ...getDefaultMiddleware({ thunk: false }),
+        ] as const,
     })
     const result1: 'A' = store.dispatch('a')
     // @ts-expect-error
diff --git a/src/tests/createAction.test.ts b/src/tests/createAction.test.ts
index ecd4b42f..b5e8b67b 100644
--- a/src/tests/createAction.test.ts
+++ b/src/tests/createAction.test.ts
@@ -1,4 +1,4 @@
-import { createAction, getType } from '../createAction'
+import { createAction, getType } from '@reduxjs/toolkit'
 
 describe('createAction', () => {
   it('should create an action', () => {
diff --git a/type-tests/files/createAction.typetest.ts b/src/tests/createAction.typetest.ts
similarity index 95%
rename from type-tests/files/createAction.typetest.ts
rename to src/tests/createAction.typetest.ts
index af17726d..73d84521 100644
--- a/type-tests/files/createAction.typetest.ts
+++ b/src/tests/createAction.typetest.ts
@@ -7,7 +7,7 @@ import {
   ActionCreatorWithOptionalPayload,
   ActionCreatorWithPayload,
   ActionCreatorWithNonInferrablePayload,
-  ActionCreatorWithPreparedPayload
+  ActionCreatorWithPreparedPayload,
 } from '@reduxjs/toolkit'
 import { IsAny } from '@internal/tsHelpers'
 import { expectType } from './helpers'
@@ -65,7 +65,7 @@ import { expectType } from './helpers'
   const actionCreator = Object.assign(
     (payload?: number) => ({
       type: 'action',
-      payload
+      payload,
     }),
     { type: 'action' }
   ) as PayloadActionCreator<number | undefined>
@@ -87,7 +87,7 @@ import { expectType } from './helpers'
   const payloadActionCreator = Object.assign(
     (payload?: number) => ({
       type: 'action',
-      payload
+      payload,
     }),
     { type: 'action' }
   ) as PayloadActionCreator
@@ -96,14 +96,14 @@ import { expectType } from './helpers'
   const payloadActionCreator2 = Object.assign(
     (payload?: number) => ({
       type: 'action',
-      payload: payload || 1
+      payload: payload || 1,
     }),
     { type: 'action' }
   ) as PayloadActionCreator<number>
 
-  const actionCreator2: ActionCreator<PayloadAction<
-    number
-  >> = payloadActionCreator2
+  const actionCreator2: ActionCreator<
+    PayloadAction<number>
+  > = payloadActionCreator2
 }
 
 /* createAction() */
@@ -146,7 +146,7 @@ import { expectType } from './helpers'
  */
 {
   const strLenAction = createAction('strLen', (payload: string) => ({
-    payload: payload.length
+    payload: payload.length,
   }))
 
   expectType<string>(strLenAction('test').type)
@@ -157,7 +157,7 @@ import { expectType } from './helpers'
  */
 {
   const strLenAction = createAction('strLen', (payload: string) => ({
-    payload: payload.length
+    payload: payload.length,
   }))
   expectType<number>(strLenAction('test').payload)
 
@@ -173,7 +173,7 @@ import { expectType } from './helpers'
 {
   const strLenMetaAction = createAction('strLenMeta', (payload: string) => ({
     payload,
-    meta: payload.length
+    meta: payload.length,
   }))
 
   expectType<number>(strLenMetaAction('test').meta)
@@ -190,7 +190,7 @@ import { expectType } from './helpers'
 {
   const boolErrorAction = createAction('boolError', (payload: string) => ({
     payload,
-    error: true
+    error: true,
   }))
 
   expectType<boolean>(boolErrorAction('test').error)
@@ -205,7 +205,7 @@ import { expectType } from './helpers'
 {
   const strErrorAction = createAction('strError', (payload: string) => ({
     payload,
-    error: 'this is an error'
+    error: 'this is an error',
   }))
 
   expectType<string>(strErrorAction('test').error)
@@ -234,7 +234,7 @@ import { expectType } from './helpers'
   const oops = createAction('oops', (x: any) => ({
     payload: x,
     error: x,
-    meta: x
+    meta: x,
   }))
 
   type Ret = ReturnType<typeof oops>
@@ -296,7 +296,7 @@ import { expectType } from './helpers'
     const actionCreator = createAction('test', () => ({
       payload: '',
       meta: '',
-      error: false
+      error: false,
     }))
     const x: Action<unknown> = {} as any
     if (actionCreator.match(x)) {
@@ -337,7 +337,7 @@ import { expectType } from './helpers'
     createAction('', (_: 0) => ({
       payload: 1 as 1,
       error: 2 as 2,
-      meta: 3 as 3
+      meta: 3 as 3,
     }))
   )
   const anyCreator = createAction<any>('')
diff --git a/src/tests/createAsyncThunk.test.ts b/src/tests/createAsyncThunk.test.ts
index b444b782..8ae9cc9f 100644
--- a/src/tests/createAsyncThunk.test.ts
+++ b/src/tests/createAsyncThunk.test.ts
@@ -1,10 +1,10 @@
 import {
   createAsyncThunk,
-  miniSerializeError,
   unwrapResult,
-} from '../createAsyncThunk'
-import { configureStore } from '../configureStore'
-import { AnyAction } from 'redux'
+  configureStore,
+  AnyAction,
+} from '@reduxjs/toolkit'
+import { miniSerializeError } from '@internal/createAsyncThunk'
 
 import {
   mockConsole,
diff --git a/type-tests/files/createAsyncThunk.typetest.ts b/src/tests/createAsyncThunk.typetest.ts
similarity index 96%
rename from type-tests/files/createAsyncThunk.typetest.ts
rename to src/tests/createAsyncThunk.typetest.ts
index 57789b22..e2e0224a 100644
--- a/type-tests/files/createAsyncThunk.typetest.ts
+++ b/src/tests/createAsyncThunk.typetest.ts
@@ -4,7 +4,7 @@ import {
   createReducer,
   AnyAction,
   unwrapResult,
-  SerializedError
+  SerializedError,
 } from '@reduxjs/toolkit'
 import { ThunkDispatch } from 'redux-thunk'
 
@@ -15,13 +15,13 @@ import { expectType } from './helpers'
 const defaultDispatch = (() => {}) as ThunkDispatch<{}, any, AnyAction>
 const anyAction = { type: 'foo' } as AnyAction
 
-  // basic usage
-;(async function() {
+// basic usage
+;(async function () {
   const async = createAsyncThunk('test', (id: number) =>
     Promise.resolve(id * 2)
   )
 
-  const reducer = createReducer({}, builder =>
+  const reducer = createReducer({}, (builder) =>
     builder
       .addCase(async.pending, (_, action) => {
         expectType<ReturnType<typeof async['pending']>>(action)
@@ -56,18 +56,18 @@ const anyAction = { type: 'foo' } as AnyAction
 
   promise
     .then(unwrapResult)
-    .then(result => {
+    .then((result) => {
       expectType<number>(result)
       // @ts-expect-error
       expectType<Error>(result)
     })
-    .catch(error => {
+    .catch((error) => {
       // catch is always any-typed, nothing we can do here
     })
 })()
 
 // More complex usage of thunk args
-;(async function() {
+;(async function () {
   interface BookModel {
     id: string
     title: string
@@ -77,7 +77,7 @@ const anyAction = { type: 'foo' } as AnyAction
 
   const fakeBooks: BookModel[] = [
     { id: 'b', title: 'Second' },
-    { id: 'a', title: 'First' }
+    { id: 'a', title: 'First' },
   ]
 
   const correctDispatch = (() => {}) as ThunkDispatch<
@@ -175,7 +175,7 @@ const anyAction = { type: 'foo' } as AnyAction
     }
   })
 
-  defaultDispatch(fetchLiveCallsError('asd')).then(result => {
+  defaultDispatch(fetchLiveCallsError('asd')).then((result) => {
     if (fetchLiveCallsError.fulfilled.match(result)) {
       //success
       expectType<ReturnType<typeof fetchLiveCallsError['fulfilled']>>(result)
@@ -194,14 +194,14 @@ const anyAction = { type: 'foo' } as AnyAction
       }
     }
     defaultDispatch(fetchLiveCallsError('asd'))
-      .then(result => {
+      .then((result) => {
         expectType<Item[] | ErrorFromServer | undefined>(result.payload)
         // @ts-expect-error
         expectType<Item[]>(unwrapped)
         return result
       })
       .then(unwrapResult)
-      .then(unwrapped => {
+      .then((unwrapped) => {
         expectType<Item[]>(unwrapped)
         // @ts-expect-error
         expectType<ErrorFromServer>(unwrapResult(unwrapped))
@@ -386,7 +386,7 @@ const anyAction = { type: 'foo' } as AnyAction
     void,
     { serializedErrorType: Funky }
   >('with generics', () => {}, {
-    serializeError: funkySerializeError
+    serializeError: funkySerializeError,
   })
 
   if (shouldWork.rejected.match(anyAction)) {
@@ -415,5 +415,7 @@ const anyAction = { type: 'foo' } as AnyAction
   const shouldFailStrArgs = createAsyncThunk('foo', () => {}, { idGenerator: returnsStrWithArgs })
 
   const returnsStrWithoutArgs = () => 'foo'
-  const shouldSucceed = createAsyncThunk('foo', () => {}, { idGenerator: returnsStrWithoutArgs })
+  const shouldSucceed = createAsyncThunk('foo', () => {}, {
+    idGenerator: returnsStrWithoutArgs,
+  })
 }
diff --git a/src/tests/createDraftSafeSelector.test.ts b/src/tests/createDraftSafeSelector.test.ts
index d4f70fab..1ae52b56 100644
--- a/src/tests/createDraftSafeSelector.test.ts
+++ b/src/tests/createDraftSafeSelector.test.ts
@@ -1,5 +1,4 @@
-import { createSelector } from 'reselect'
-import { createDraftSafeSelector } from '../createDraftSafeSelector'
+import { createDraftSafeSelector, createSelector } from '@reduxjs/toolkit'
 import { produce } from 'immer'
 
 type State = { value: number }
diff --git a/type-tests/files/createEntityAdapter.typetest.ts b/src/tests/createEntityAdapter.typetest.ts
similarity index 93%
rename from type-tests/files/createEntityAdapter.typetest.ts
rename to src/tests/createEntityAdapter.typetest.ts
index 5754761c..fddb312f 100644
--- a/type-tests/files/createEntityAdapter.typetest.ts
+++ b/src/tests/createEntityAdapter.typetest.ts
@@ -6,7 +6,7 @@ import {
   ActionCreatorWithoutPayload,
   EntityStateAdapter,
   EntityId,
-  Update
+  Update,
 } from '@reduxjs/toolkit'
 import { expectType } from './helpers'
 
@@ -35,8 +35,8 @@ function extractReducers<T>(
     name: 'test',
     initialState: adapter.getInitialState(),
     reducers: {
-      ...extractReducers(adapter)
-    }
+      ...extractReducers(adapter),
+    },
   })
 
   expectType<ActionCreatorWithPayload<Entity>>(slice.actions.addOne)
@@ -77,8 +77,8 @@ function extractReducers<T>(
     reducers: {
       addOne: adapter.addOne,
       // @ts-expect-error
-      addOne2: adapter2.addOne
-    }
+      addOne2: adapter2.addOne,
+    },
   })
 }
 
@@ -94,8 +94,8 @@ function extractReducers<T>(
     name: 'test',
     initialState: adapter.getInitialState({ extraData: 'test' }),
     reducers: {
-      addOne: adapter.addOne
-    }
+      addOne: adapter.addOne,
+    },
   })
 }
 
@@ -112,7 +112,7 @@ function extractReducers<T>(
     initialState: { somethingElse: '' },
     reducers: {
       // @ts-expect-error
-      addOne: adapter.addOne
-    }
+      addOne: adapter.addOne,
+    },
   })
 }
diff --git a/src/tests/createReducer.test.ts b/src/tests/createReducer.test.ts
index b76b9970..59781c2a 100644
--- a/src/tests/createReducer.test.ts
+++ b/src/tests/createReducer.test.ts
@@ -1,7 +1,13 @@
-import { createReducer, CaseReducer } from '../createReducer'
-import { PayloadAction, createAction } from '../createAction'
-import { createNextState, Draft } from '..'
-import { Reducer, AnyAction } from 'redux'
+import {
+  createReducer,
+  CaseReducer,
+  PayloadAction,
+  createAction,
+  createNextState,
+  Draft,
+  Reducer,
+  AnyAction,
+} from '@reduxjs/toolkit'
 
 interface Todo {
   text: string
diff --git a/type-tests/files/createReducer.typetest.ts b/src/tests/createReducer.typetest.ts
similarity index 89%
rename from type-tests/files/createReducer.typetest.ts
rename to src/tests/createReducer.typetest.ts
index 14edaa19..b1fd3af1 100644
--- a/type-tests/files/createReducer.typetest.ts
+++ b/src/tests/createReducer.typetest.ts
@@ -2,7 +2,7 @@ import { Reducer } from 'redux'
 import {
   createReducer,
   createAction,
-  ActionReducerMapBuilder
+  ActionReducerMapBuilder,
 } from '@reduxjs/toolkit'
 import { expectType } from './helpers'
 
@@ -19,7 +19,7 @@ import { expectType } from './helpers'
 
   const reducer = createReducer(0 as number, {
     increment: incrementHandler,
-    decrement: decrementHandler
+    decrement: decrementHandler,
   })
 
   const numberReducer: Reducer<number> = reducer
@@ -44,13 +44,13 @@ import { expectType } from './helpers'
 
   createReducer<number>(0, {
     increment: incrementHandler,
-    decrement: decrementHandler
+    decrement: decrementHandler,
   })
 
   // @ts-expect-error
   createReducer<string>(0, {
     increment: incrementHandler,
-    decrement: decrementHandler
+    decrement: decrementHandler,
   })
 }
 
@@ -61,9 +61,9 @@ import { expectType } from './helpers'
   const initialState: { readonly counter: number } = { counter: 0 }
 
   createReducer(initialState, {
-    increment: state => {
+    increment: (state) => {
       state.counter += 1
-    }
+    },
   })
 }
 
@@ -71,7 +71,7 @@ import { expectType } from './helpers'
 {
   const increment = createAction<number, 'increment'>('increment')
 
-  const reducer = createReducer(0, builder =>
+  const reducer = createReducer(0, (builder) =>
     expectType<ActionReducerMapBuilder<number>>(builder)
   )
 
diff --git a/src/tests/createSlice.test.ts b/src/tests/createSlice.test.ts
index 1baad4c7..d49a3097 100644
--- a/src/tests/createSlice.test.ts
+++ b/src/tests/createSlice.test.ts
@@ -1,5 +1,4 @@
-import { createSlice } from '../createSlice'
-import { createAction, PayloadAction } from '../createAction'
+import { createSlice, createAction, PayloadAction } from '@reduxjs/toolkit'
 
 describe('createSlice', () => {
   describe('when slice is undefined', () => {
diff --git a/type-tests/files/createSlice.typetest.ts b/src/tests/createSlice.typetest.ts
similarity index 91%
rename from type-tests/files/createSlice.typetest.ts
rename to src/tests/createSlice.typetest.ts
index 1039a8a4..70b1c5ca 100644
--- a/type-tests/files/createSlice.typetest.ts
+++ b/src/tests/createSlice.typetest.ts
@@ -10,7 +10,7 @@ import {
   createSlice,
   PayloadAction,
   SliceCaseReducers,
-  ValidateSliceCaseReducers
+  ValidateSliceCaseReducers,
 } from '@reduxjs/toolkit'
 import { expectType } from './helpers'
 
@@ -23,8 +23,8 @@ const counterSlice = createSlice({
   initialState: 0,
   reducers: {
     increment: (state: number, action) => state + action.payload,
-    decrement: (state: number, action) => state - action.payload
-  }
+    decrement: (state: number, action) => state - action.payload,
+  },
 })
 
 const uiSlice = createSlice({
@@ -32,13 +32,13 @@ const uiSlice = createSlice({
   initialState: 0,
   reducers: {
     goToNext: (state: number, action) => state + action.payload,
-    goToPrevious: (state: number, action) => state - action.payload
-  }
+    goToPrevious: (state: number, action) => state - action.payload,
+  },
 })
 
 const actionCreators = {
   [counterSlice.name]: { ...counterSlice.actions },
-  [uiSlice.name]: { ...uiSlice.actions }
+  [uiSlice.name]: { ...uiSlice.actions },
 }
 
 expectType<typeof counterSlice.actions>(actionCreators.counter)
@@ -58,12 +58,12 @@ const value = actionCreators.anyKey
     initialState: 0,
     reducers: {
       increment: (state: number, action) => state + action.payload,
-      decrement: (state: number, action) => state - action.payload
+      decrement: (state: number, action) => state - action.payload,
     },
     extraReducers: {
       [firstAction.type]: (state: number, action) =>
-        state + action.payload.count
-    }
+        state + action.payload.count,
+    },
   })
 
   /* Reducer */
@@ -92,7 +92,7 @@ const value = actionCreators.anyKey
     name: 'counter',
     initialState: 0,
     reducers: {
-      increment: state => state + 1,
+      increment: (state) => state + 1,
       decrement: (state, { payload = 1 }: PayloadAction<number | undefined>) =>
         state - payload,
       multiply: (state, { payload }: PayloadAction<number | number[]>) =>
@@ -102,10 +102,10 @@ const value = actionCreators.anyKey
       addTwo: {
         reducer: (s, { payload }: PayloadAction<number>) => s + payload,
         prepare: (a: number, b: number) => ({
-          payload: a + b
-        })
-      }
-    }
+          payload: a + b,
+        }),
+      },
+    },
   })
 
   expectType<ActionCreatorWithoutPayload>(counter.actions.increment)
@@ -146,13 +146,13 @@ const value = actionCreators.anyKey
     name: 'counter',
     initialState: 0,
     reducers: {
-      increment: state => state + 1,
-      decrement: state => state - 1,
+      increment: (state) => state + 1,
+      decrement: (state) => state - 1,
       multiply: (state, { payload }: PayloadAction<number | number[]>) =>
         Array.isArray(payload)
           ? payload.reduce((acc, val) => acc * val, state)
-          : state * payload
-    }
+          : state * payload,
+    },
   })
 
   const s: string = counter.actions.increment.type
@@ -178,8 +178,8 @@ const value = actionCreators.anyKey
           state.counter += action.payload
         },
         prepare: (payload: string) => ({
-          payload: payload.length
-        })
+          payload: payload.length,
+        }),
       },
       concatMetaStrLen: {
         reducer: (state, action: PayloadAction<string>) => {
@@ -187,10 +187,10 @@ const value = actionCreators.anyKey
         },
         prepare: (payload: string) => ({
           payload,
-          meta: payload.length
-        })
-      }
-    }
+          meta: payload.length,
+        }),
+      },
+    },
   })
 
   expectType<string>(counter.actions.incrementByStrLen('test').type)
@@ -219,8 +219,8 @@ const value = actionCreators.anyKey
         prepare: (payload: number) => ({
           payload,
           meta: 'meta' as 'meta',
-          error: 'error' as 'error'
-        })
+          error: 'error' as 'error',
+        }),
       },
       // case: meta and error marked as "unknown" in reducer
       testUnknownMetaAndError: {
@@ -228,8 +228,8 @@ const value = actionCreators.anyKey
         prepare: (payload: number) => ({
           payload,
           meta: 'meta' as 'meta',
-          error: 'error' as 'error'
-        })
+          error: 'error' as 'error',
+        }),
       },
       // case: meta and error are typed in the reducer as returned by prepare
       testMetaAndError: {
@@ -237,8 +237,8 @@ const value = actionCreators.anyKey
         prepare: (payload: number) => ({
           payload,
           meta: 'meta' as 'meta',
-          error: 'error' as 'error'
-        })
+          error: 'error' as 'error',
+        }),
       },
       // case: meta is typed differently in the reducer than returned from prepare
       testErroneousMeta: {
@@ -247,8 +247,8 @@ const value = actionCreators.anyKey
         prepare: (payload: number) => ({
           payload,
           meta: 1,
-          error: 'error' as 'error'
-        })
+          error: 'error' as 'error',
+        }),
       },
       // case: error is typed differently in the reducer than returned from prepare
       testErroneousError: {
@@ -257,10 +257,10 @@ const value = actionCreators.anyKey
         prepare: (payload: number) => ({
           payload,
           meta: 'meta' as 'meta',
-          error: 1
-        })
-      }
-    }
+          error: 1,
+        }),
+      },
+    },
   })
 }
 
@@ -281,9 +281,9 @@ const value = actionCreators.anyKey
         },
         prepare(amount: number) {
           return { payload: amount }
-        }
-      }
-    }
+        },
+      },
+    },
   })
 
   // Should match positively
@@ -333,11 +333,11 @@ const value = actionCreators.anyKey
         // @ts-expect-error
         prepare(x: string) {
           return {
-            payload: 6
+            payload: 6,
           }
-        }
-      }
-    }
+        },
+      },
+    },
   })
 }
 
@@ -347,7 +347,7 @@ const value = actionCreators.anyKey
  */
 {
   const initialState = {
-    name: null
+    name: null,
   }
 
   const mySlice = createSlice({
@@ -356,8 +356,8 @@ const value = actionCreators.anyKey
     reducers: {
       setName: (state, action) => {
         state.name = action.payload
-      }
-    }
+      },
+    },
   })
 
   expectType<ActionCreatorWithNonInferrablePayload>(mySlice.actions.setName)
@@ -379,8 +379,8 @@ const value = actionCreators.anyKey
     reducers: {
       setName: (state, action: PayloadAction<string>) => {
         state.name = action.payload
-      }
-    }
+      },
+    },
   })
 
   const x: Action<unknown> = {} as any
@@ -401,9 +401,9 @@ const value = actionCreators.anyKey
     name: 'test',
     initialState: 0,
     reducers: {},
-    extraReducers: builder => {
+    extraReducers: (builder) => {
       expectType<ActionReducerMapBuilder<number>>(builder)
-    }
+    },
   })
 }
 
@@ -420,7 +420,7 @@ const value = actionCreators.anyKey
   >({
     name = '',
     initialState,
-    reducers
+    reducers,
   }: {
     name: string
     initialState: GenericState<T>
@@ -437,8 +437,8 @@ const value = actionCreators.anyKey
           state.data = action.payload
           state.status = 'finished'
         },
-        ...reducers
-      }
+        ...reducers,
+      },
     })
   }
 
@@ -453,8 +453,8 @@ const value = actionCreators.anyKey
 
         state.status = 'finished'
         state.data = 'hocus pocus'
-      }
-    }
+      },
+    },
   })
 
   expectType<ActionCreatorWithPayload<string>>(wrappedSlice.actions.success)
@@ -481,17 +481,17 @@ const value = actionCreators.anyKey
       name,
       initialState,
       reducers,
-      extraReducers: builder => {
-        builder.addCase(doNothing, state => {
+      extraReducers: (builder) => {
+        builder.addCase(doNothing, (state) => {
           return { ...state }
         })
         builder.addCase(setData, (state, { payload }) => {
           return {
             ...state,
-            data: payload
+            data: payload,
           }
         })
-      }
+      },
     })
     return { doNothing, setData, slice }
   }
diff --git a/src/tests/getDefaultMiddleware.test.ts b/src/tests/getDefaultMiddleware.test.ts
index ca7078f4..2c94ad9c 100644
--- a/src/tests/getDefaultMiddleware.test.ts
+++ b/src/tests/getDefaultMiddleware.test.ts
@@ -1,6 +1,12 @@
-import { AnyAction, Middleware } from 'redux'
-import { getDefaultMiddleware, MiddlewareArray, configureStore } from '..'
-import thunk, { ThunkAction } from 'redux-thunk'
+import {
+  AnyAction,
+  Middleware,
+  getDefaultMiddleware,
+  MiddlewareArray,
+  configureStore,
+  ThunkAction,
+} from '@reduxjs/toolkit'
+import thunk from 'redux-thunk'
 
 describe('getDefaultMiddleware', () => {
   const ORIGINAL_NODE_ENV = process.env.NODE_ENV
@@ -12,7 +18,7 @@ describe('getDefaultMiddleware', () => {
   it('returns an array with only redux-thunk in production', () => {
     process.env.NODE_ENV = 'production'
 
-    expect(getDefaultMiddleware()).toEqual([thunk])
+    expect(getDefaultMiddleware()).toEqual([thunk]) // @remap-prod-remove-line
   })
 
   it('returns an array with additional middleware in development', () => {
diff --git a/type-tests/files/helpers.ts b/src/tests/helpers.ts
similarity index 100%
rename from type-tests/files/helpers.ts
rename to src/tests/helpers.ts
diff --git a/src/tests/immutableStateInvariantMiddleware.test.ts b/src/tests/immutableStateInvariantMiddleware.test.ts
index 080d25f7..a163ab43 100644
--- a/src/tests/immutableStateInvariantMiddleware.test.ts
+++ b/src/tests/immutableStateInvariantMiddleware.test.ts
@@ -1,10 +1,13 @@
-import { Store, MiddlewareAPI, Dispatch } from 'redux'
 import {
+  Store,
+  MiddlewareAPI,
+  Dispatch,
   createImmutableStateInvariantMiddleware,
   isImmutableDefault,
-  trackForMutations,
   ImmutableStateInvariantMiddlewareOptions,
-} from '../immutableStateInvariantMiddleware'
+} from '@reduxjs/toolkit'
+
+import { trackForMutations } from '@internal/immutableStateInvariantMiddleware'
 import { mockConsole, createConsole, getLog } from 'console-testing-library'
 
 describe('createImmutableStateInvariantMiddleware', () => {
diff --git a/src/tests/isPlainObject.test.ts b/src/tests/isPlainObject.test.ts
index 178ad487..59b04e22 100644
--- a/src/tests/isPlainObject.test.ts
+++ b/src/tests/isPlainObject.test.ts
@@ -1,4 +1,4 @@
-import isPlainObject from '../isPlainObject'
+import { isPlainObject } from '@reduxjs/toolkit'
 import vm from 'vm'
 
 describe('isPlainObject', () => {
diff --git a/type-tests/files/mapBuilders.typetest.ts b/src/tests/mapBuilders.typetest.ts
similarity index 98%
rename from type-tests/files/mapBuilders.typetest.ts
rename to src/tests/mapBuilders.typetest.ts
index 2516da60..8df53505 100644
--- a/type-tests/files/mapBuilders.typetest.ts
+++ b/src/tests/mapBuilders.typetest.ts
@@ -7,7 +7,7 @@ import { expectType } from './helpers'
   const increment = createAction<number, 'increment'>('increment')
   const decrement = createAction<number, 'decrement'>('decrement')
 
-  executeReducerBuilderCallback<number>(builder => {
+  executeReducerBuilderCallback<number>((builder) => {
     builder.addCase(increment, (state, action) => {
       expectType<number>(state)
       expectType<{ type: 'increment'; payload: number }>(action)
diff --git a/src/tests/matchers.test.ts b/src/tests/matchers.test.ts
index 7b8b2080..02f2c823 100644
--- a/src/tests/matchers.test.ts
+++ b/src/tests/matchers.test.ts
@@ -6,12 +6,12 @@ import {
   isPending,
   isRejected,
   isRejectedWithValue,
-} from '../matchers'
-import { createAction } from '../createAction'
-import { createAsyncThunk } from '../createAsyncThunk'
-import { createReducer } from '../createReducer'
-import { ThunkAction } from 'redux-thunk'
-import { AnyAction } from 'redux'
+  createAction,
+  createAsyncThunk,
+  createReducer,
+  ThunkAction,
+  AnyAction,
+} from '@reduxjs/toolkit'
 
 const thunk: ThunkAction<any, any, any, AnyAction> = () => {}
 
diff --git a/type-tests/files/matchers.typetest.ts b/src/tests/matchers.typetest.ts
similarity index 94%
rename from type-tests/files/matchers.typetest.ts
rename to src/tests/matchers.typetest.ts
index 83a9edb4..5cc19bf2 100644
--- a/type-tests/files/matchers.typetest.ts
+++ b/src/tests/matchers.typetest.ts
@@ -1,3 +1,4 @@
+import { expectExactType, expectUnknown } from './helpers'
 import { IsUnknown } from '@internal/tsHelpers'
 import { AnyAction } from 'redux'
 import {
@@ -10,7 +11,7 @@ import {
   isPending,
   isRejected,
   isRejectedWithValue,
-  SerializedError
+  SerializedError,
 } from '../../src'
 
 /* isAnyOf */
@@ -23,8 +24,8 @@ function isAnyOfActionTest(action: AnyAction) {
     return {
       payload: {
         prop1: 1,
-        prop3: 2
-      }
+        prop3: 2,
+      },
     }
   })
 
@@ -32,8 +33,8 @@ function isAnyOfActionTest(action: AnyAction) {
     return {
       payload: {
         prop1: 1,
-        prop2: 2
-      }
+        prop2: 2,
+      },
     }
   })
 
@@ -43,7 +44,7 @@ function isAnyOfActionTest(action: AnyAction) {
       // @ts-expect-error
       prop2: action.payload.prop2,
       // @ts-expect-error
-      prop3: action.payload.prop3
+      prop3: action.payload.prop3,
     }
   }
 }
@@ -58,7 +59,7 @@ function isAnyOfThunkTest(action: AnyAction) {
     async () => {
       return {
         prop1: 1,
-        prop3: 3
+        prop3: 3,
       }
     }
   )
@@ -69,7 +70,7 @@ function isAnyOfThunkTest(action: AnyAction) {
     async () => {
       return {
         prop1: 1,
-        prop2: 2
+        prop2: 2,
       }
     }
   )
@@ -80,7 +81,7 @@ function isAnyOfThunkTest(action: AnyAction) {
       // @ts-expect-error
       prop2: action.payload.prop2,
       // @ts-expect-error
-      prop3: action.payload.prop3
+      prop3: action.payload.prop3,
     }
   }
 }
@@ -119,7 +120,7 @@ function isAnyOfTypeGuardTest(action: AnyAction) {
       // @ts-expect-error
       prop2: action.payload.prop2,
       // @ts-expect-error
-      prop3: action.payload.prop3
+      prop3: action.payload.prop3,
     }
   }
 }
@@ -145,8 +146,8 @@ function isAllOfActionTest(action: AnyAction) {
     return {
       payload: {
         prop1: 1,
-        prop3: 2
-      }
+        prop3: 2,
+      },
     }
   })
 
@@ -156,7 +157,7 @@ function isAllOfActionTest(action: AnyAction) {
       // @ts-expect-error
       prop2: action.payload.prop2,
       prop3: action.payload.prop3,
-      special: action.payload.special
+      special: action.payload.special,
     }
   }
 }
@@ -172,7 +173,7 @@ function isAllOfThunkTest(action: AnyAction) {
     async () => {
       return {
         prop1: 1,
-        prop3: 3
+        prop3: 3,
       }
     }
   )
@@ -183,7 +184,7 @@ function isAllOfThunkTest(action: AnyAction) {
       // @ts-expect-error
       prop2: action.payload.prop2,
       prop3: action.payload.prop3,
-      special: action.payload.special
+      special: action.payload.special,
     }
   }
 }
@@ -210,7 +211,7 @@ function isAllOfTypeGuardTest(action: AnyAction) {
       // @ts-expect-error
       prop2: action.payload.prop2,
       prop3: action.payload.prop3,
-      special: action.payload.special
+      special: action.payload.special,
     }
   }
 }
@@ -311,5 +312,3 @@ function isRejectedWithValueTest(action: AnyAction) {
     expectExactType<SerializedError>(action.error)
   }
 }
-
-import { expectExactType, expectUnknown } from './helpers'
diff --git a/src/tests/serializableStateInvariantMiddleware.test.ts b/src/tests/serializableStateInvariantMiddleware.test.ts
index 7929fbcb..833f5e16 100644
--- a/src/tests/serializableStateInvariantMiddleware.test.ts
+++ b/src/tests/serializableStateInvariantMiddleware.test.ts
@@ -1,16 +1,15 @@
-import { Reducer } from 'redux'
 import {
   mockConsole,
   createConsole,
   getLog,
 } from 'console-testing-library/pure'
-import { configureStore } from '../configureStore'
-
 import {
+  Reducer,
+  configureStore,
   createSerializableStateInvariantMiddleware,
   findNonSerializableValue,
   isPlain,
-} from '../serializableStateInvariantMiddleware'
+} from '@reduxjs/toolkit'
 
 // Mocking console
 let restore = () => {}
diff --git a/src/tests/tsconfig.json b/src/tests/tsconfig.json
new file mode 100644
index 00000000..36781645
--- /dev/null
+++ b/src/tests/tsconfig.json
@@ -0,0 +1,3 @@
+{
+  "extends": "../../tsconfig.test.json"
+}
diff --git a/tsconfig.test.json b/tsconfig.test.json
index eaf0c45d..62e6ee81 100644
--- a/tsconfig.test.json
+++ b/tsconfig.test.json
@@ -5,11 +5,13 @@
     "esModuleInterop": true,
     "module": "esnext",
     "moduleResolution": "node",
+    "emitDeclarationOnly": false,
     "strict": true,
     "noEmit": true,
     "target": "es2018",
     "jsx": "react",
     "baseUrl": ".",
-    "skipLibCheck": true
+    "skipLibCheck": true,
+    "noImplicitReturns": false
   }
 }
diff --git a/type-tests/files/tsconfig.json b/type-tests/files/tsconfig.json
deleted file mode 100644
index b0a5d437..00000000
--- a/type-tests/files/tsconfig.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "compilerOptions": {
-    "allowSyntheticDefaultImports": true,
-    "esModuleInterop": true,
-    "module": "es2015",
-    "moduleResolution": "node",
-    "strict": true,
-    "noEmit": true,
-    "target": "es2018",
-    "baseUrl": "../..",
-    "paths": {
-      "@reduxjs/toolkit": ["./src"],
-      "@internal/*": ["./src/*"]
-    }
-  }
-}
diff --git a/type-tests/lib.ts b/type-tests/lib.ts
deleted file mode 100644
index 0128e2bd..00000000
--- a/type-tests/lib.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { check } from 'typings-tester'
-import { versionMajorMinor, sys, findConfigFile } from 'typescript'
-
-export const tsVersion = Number.parseFloat(versionMajorMinor)
-
-export const testIf = (condition: boolean) => (condition ? test : test.skip)
-
-export function checkDirectory(path: string, bail: boolean = false, depth = 1) {
-  const files = sys.readDirectory(path, ['.ts', '.tsx'], [], [], depth)
-  const tsConfigPath = findConfigFile(path, sys.fileExists)
-
-  if (!tsConfigPath) {
-    throw new Error(`Cannot find TypeScript config file in ${path}.`)
-  }
-
-  check(files, tsConfigPath, bail)
-}
-
-export function checkFile(path: string, bail: boolean = false, depth = 1) {
-  const tsConfigPath = findConfigFile(path, sys.fileExists)
-
-  if (!tsConfigPath) {
-    throw new Error(`Cannot find TypeScript config file in ${path}.`)
-  }
-
-  check([path], tsConfigPath, bail)
-}
diff --git a/type-tests/types.test.disabled.ts b/type-tests/types.test.disabled.ts
deleted file mode 100644
index 846d683c..00000000
--- a/type-tests/types.test.disabled.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { checkDirectory } from './lib'
-
-test('Types', () => {
-  checkDirectory(`${__dirname}/files`)
-})