From a42105b56309afd02f1febe584a28c34ed87da45 Mon Sep 17 00:00:00 2001 From: Shrugsy Date: Sat, 24 Apr 2021 17:01:07 +1000 Subject: [PATCH 01/11] Add full types to useMutation's returned callback --- query-old/docs/api/created-api/hooks.md | 42 ++++++++++---- src/createAsyncThunk.ts | 2 +- src/query/core/buildInitiate.ts | 77 ++++++++++++++++++++++++- src/query/react/buildHooks.ts | 32 +--------- src/query/tests/buildHooks.test.tsx | 64 +++++++++++++++++++- 5 files changed, 173 insertions(+), 44 deletions(-) diff --git a/query-old/docs/api/created-api/hooks.md b/query-old/docs/api/created-api/hooks.md index c7303c18df..0386d676b7 100644 --- a/query-old/docs/api/created-api/hooks.md +++ b/query-old/docs/api/created-api/hooks.md @@ -68,7 +68,7 @@ type UseQueryResult = { 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 "error" state. + isError: false; // Query is currently in an "error" state. refetch: () => void; // A function to force refetch the query }; @@ -91,18 +91,40 @@ The query arg is used as a cache key. Changing the query arg will tell the hook #### Signature ```ts -type MutationHook = () => [ - ( - arg: any - ) => { - unwrap: () => Promise>; - }, - MutationSubState & RequestStatusFlags -]; +type UseMutation = () => [UseMutationTrigger, UseMutationResult]; + +type UseMutationTrigger = ( + arg: ArgTypeFrom +) => Promise<{ data: ResultTypeFrom }> & { + arg: { + endpointName: string; // The name of the given endpoint for the mutation + originalArgs: ArgTypeFrom; // Arguments passed to the mutation + track?: boolean; // Whether the mutation is being tracked in the store + startedTimeStamp: number; // Timestamp for when the mutation was initiated + }; + requestId: string; // A string generated by RTK Query + abort: () => void; // A method to cancel the mutation promise + unwrap: () => Promise>; // 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 = { + data?: ResultTypeFrom; // 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; // Arguments passed to the latest mutation call + startedTimeStamp?: number; // Timestamp for when the latest mutation was initiated + status: 'uninitialized' | 'pending' | 'fulfilled' | 'rejected'; // @deprecated - A string describing the mutation state +}; ``` - **Returns**: a tuple containing: - - `trigger`: a function that triggers an update to the data based on the provided argument + - `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 #### Description diff --git a/src/createAsyncThunk.ts b/src/createAsyncThunk.ts index 8b2b588202..55bc50c04e 100644 --- a/src/createAsyncThunk.ts +++ b/src/createAsyncThunk.ts @@ -144,7 +144,7 @@ export type AsyncThunkPayloadCreator< * A ThunkAction created by `createAsyncThunk`. * Dispatching it returns a Promise for either a * fulfilled or rejected action. - * Also, the returned value contains a `abort()` method + * Also, the returned value contains an `abort()` method * that allows the asyncAction to be cancelled from the outside. * * @public diff --git a/src/query/core/buildInitiate.ts b/src/query/core/buildInitiate.ts index 8efb99fe95..333bedc3d8 100644 --- a/src/query/core/buildInitiate.ts +++ b/src/query/core/buildInitiate.ts @@ -87,10 +87,85 @@ export type MutationActionCreatorResult< > > > & { - arg: QueryArgFrom + arg: { + /** + * The name of the given endpoint for the mutation + */ + endpointName: string + /** + * The original arguments supplied to the mutation call + */ + originalArgs: QueryArgFrom + /** + * Whether the mutation is being tracked in the store. + */ + track?: boolean + /** + * Timestamp for when the mutation was initiated + */ + startedTimeStamp: number + } + /** + * A unique string generated for the request sequence + */ requestId: string + /** + * A method to cancel the mutation promise. Note that this is not intended to prevent the mutation + * that was fired off from reaching the server, but only to assist in handling the response. + * + * Calling `abort()` prior to the promise resolving will make it throw with an error like: + * `{ name: 'AbortError', message: 'Aborted' }` + * + * @example + * ```ts + * const [updateUser] = useUpdateUserMutation(); + * + * useEffect(() => { + * const promise = updateUser(id); + * promise + * .unwrap() + * .catch((err) => { + * if (err.name === 'AbortError') return; + * // else handle the unexpected error + * }) + * + * return () => { + * promise.abort(); + * } + * }, [id, updateUser]) + * ``` + */ abort(): void + /** + * Unwraps a mutation call to provide the raw response/error. + * + * @remarks + * If you need to access the error or success payload immediately after a mutation, you can chain .unwrap(). + * + * @example + * ```ts + * // codeblock-meta title="Using .unwrap" + * addPost({ id: 1, name: 'Example' }) + * .unwrap() + * .then((payload) => console.log('fulfilled', payload)) + * .catch((error) => console.error('rejected', error)); + * ``` + * + * @example + * ```ts + * // codeblock-meta title="Using .unwrap with async await" + * try { + * const payload = await addPost({ id: 1, name: 'Example' }).unwrap(); + * console.log('fulfilled', payload) + * } catch (error) { + * console.error('rejected', error); + * } + * ``` + */ unwrap(): Promise> + /** + * A method to manually unsubscribe from the mutation call + */ unsubscribe(): void } diff --git a/src/query/react/buildHooks.ts b/src/query/react/buildHooks.ts index 9e9545184b..51c7c34e7a 100644 --- a/src/query/react/buildHooks.ts +++ b/src/query/react/buildHooks.ts @@ -321,37 +321,7 @@ export type UseMutation> = < >( options?: UseMutationStateOptions ) => [ - ( - arg: QueryArgFrom - ) => { - /** - * Unwraps a mutation call to provide the raw response/error. - * - * @remarks - * If you need to access the error or success payload immediately after a mutation, you can chain .unwrap(). - * - * @example - * ```ts - * // codeblock-meta title="Using .unwrap" - * addPost({ id: 1, name: 'Example' }) - * .unwrap() - * .then((payload) => console.log('fulfilled', payload)) - * .catch((error) => console.error('rejected', error)); - * ``` - * - * @example - * ```ts - * // codeblock-meta title="Using .unwrap with async await" - * try { - * const payload = await addPost({ id: 1, name: 'Example' }).unwrap(); - * console.log('fulfilled', payload) - * } catch (error) { - * console.error('rejected', error); - * } - * ``` - */ - unwrap: () => Promise> - }, + (arg: QueryArgFrom) => MutationActionCreatorResult, UseMutationStateResult ] diff --git a/src/query/tests/buildHooks.test.tsx b/src/query/tests/buildHooks.test.tsx index f52a527ff5..fc3a26d2eb 100644 --- a/src/query/tests/buildHooks.test.tsx +++ b/src/query/tests/buildHooks.test.tsx @@ -6,6 +6,7 @@ import { rest } from 'msw' import { actionsReducer, expectExactType, + expectType, matchSequence, setupApiStore, useRenderCounter, @@ -44,7 +45,7 @@ const api = createApi({ }, }), }), - updateUser: build.mutation({ + updateUser: build.mutation<{ name: string }, { name: string }>({ query: (update) => ({ body: update }), }), getError: build.query({ @@ -804,6 +805,67 @@ describe('hooks tests', () => { ) ) }) + + test('useMutation hook callback returns various properties to handle the result', async () => { + function User() { + const [updateUser] = api.endpoints.updateUser.useMutation() + const [successMsg, setSuccessMsg] = React.useState('') + const [errMsg, setErrMsg] = React.useState('') + const [isAborted, setIsAborted] = React.useState(false) + + const handleClick = () => { + const res = updateUser({ name: 'Banana' }) + expectType<{ + endpointName: string + originalArgs: { name: string } + track?: boolean + startedTimeStamp: number + }>(res.arg) + expectType(res.requestId) + expectType<() => void>(res.abort) + expectType<() => Promise<{ name: string }>>(res.unwrap) + expectType<() => void>(res.unsubscribe) + + // abort the mutation immediately to force an error + res.abort() + res + .unwrap() + .then((result) => { + expectType<{ name: string }>(result) + setSuccessMsg(`Successfully updated user ${result.name}`) + }) + .catch((err) => { + setErrMsg( + `An error has occurred updating user ${res.arg.originalArgs.name}` + ) + if (err.name === 'AbortError') { + setIsAborted(true) + } + }) + } + + return ( +
+ +
{successMsg}
+
{errMsg}
+
{isAborted ? 'Request was aborted' : ''}
+
+ ) + } + + render(, { wrapper: storeRef.wrapper }) + expect(screen.queryByText(/An error has occurred/i)).toBeNull() + expect(screen.queryByText(/Successfully updated user/i)).toBeNull() + expect(screen.queryByText('Request was aborted')).toBeNull() + + fireEvent.click( + screen.getByRole('button', { name: 'Update User and abort' }) + ) + await screen.findByText('An error has occurred updating user Banana') + expect(screen.queryByText(/Successfully updated user/i)).toBeNull() + screen.getByText('Request was aborted') + }) }) describe('usePrefetch', () => { From 36ecc80e3b85e8185a8eceb4ca0e73ae56dbe84b Mon Sep 17 00:00:00 2001 From: Shrugsy Date: Sat, 24 Apr 2021 18:36:58 +1000 Subject: [PATCH 02/11] Apply suggestions from code review Co-authored-by: Lenz Weber --- query-old/docs/api/created-api/hooks.md | 1 - src/query/core/buildInitiate.ts | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/query-old/docs/api/created-api/hooks.md b/query-old/docs/api/created-api/hooks.md index 0386d676b7..f369861829 100644 --- a/query-old/docs/api/created-api/hooks.md +++ b/query-old/docs/api/created-api/hooks.md @@ -119,7 +119,6 @@ type UseMutationResult = { isUninitialized: boolean; // Mutation has not been fired yet originalArgs?: ArgTypeFrom; // Arguments passed to the latest mutation call startedTimeStamp?: number; // Timestamp for when the latest mutation was initiated - status: 'uninitialized' | 'pending' | 'fulfilled' | 'rejected'; // @deprecated - A string describing the mutation state }; ``` diff --git a/src/query/core/buildInitiate.ts b/src/query/core/buildInitiate.ts index 333bedc3d8..5d2417ded2 100644 --- a/src/query/core/buildInitiate.ts +++ b/src/query/core/buildInitiate.ts @@ -87,6 +87,7 @@ export type MutationActionCreatorResult< > > > & { + /** @internal */ arg: { /** * The name of the given endpoint for the mutation @@ -164,7 +165,8 @@ export type MutationActionCreatorResult< */ unwrap(): Promise> /** - * A method to manually unsubscribe from the mutation call + * A method to manually unsubscribe from the mutation call, meaning it will be removed from cache after the usual caching grace period. + The value returned by the hook will reset to `isUninitialized` afterwards. */ unsubscribe(): void } From 2bb34a93d22082555e3c09ecd9864dcc3bf44042 Mon Sep 17 00:00:00 2001 From: Shrugsy Date: Sat, 24 Apr 2021 19:39:24 +1000 Subject: [PATCH 03/11] Tweak promise result type for useMutation trigger --- src/query/core/buildInitiate.ts | 20 ++++++++++++-------- src/query/tests/buildHooks.test.tsx | 29 ++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/query/core/buildInitiate.ts b/src/query/core/buildInitiate.ts index 5d2417ded2..3f96ac3c63 100644 --- a/src/query/core/buildInitiate.ts +++ b/src/query/core/buildInitiate.ts @@ -11,12 +11,13 @@ import { AsyncThunk, ThunkAction, unwrapResult, + SerializedError, } from '@reduxjs/toolkit' import { QuerySubState, SubscriptionOptions } from './apiState' import { InternalSerializeQueryArgs } from '../defaultSerializeQueryArgs' import { Api } from '../apiTypes' import { ApiEndpointQuery } from './module' -import { BaseQueryResult } from '../baseQueryTypes' +import { BaseQueryError } from '../baseQueryTypes' declare module './module' { export interface ApiEndpointQuery< @@ -79,13 +80,16 @@ type StartMutationActionCreator< export type MutationActionCreatorResult< D extends MutationDefinition > = Promise< - ReturnType< - BaseQueryResult< - D extends MutationDefinition - ? BaseQuery - : never - > - > + | { data: ResultTypeFrom } + | { + error: + | BaseQueryError< + D extends MutationDefinition + ? BaseQuery + : never + > + | SerializedError + } > & { /** @internal */ arg: { diff --git a/src/query/tests/buildHooks.test.tsx b/src/query/tests/buildHooks.test.tsx index fc3a26d2eb..6aae2fcf6d 100644 --- a/src/query/tests/buildHooks.test.tsx +++ b/src/query/tests/buildHooks.test.tsx @@ -15,6 +15,7 @@ import { import { server } from './mocks/server' import { AnyAction } from 'redux' import { SubscriptionOptions } from '../core/apiState' +import { SerializedError } from '../../createAsyncThunk' // 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 @@ -27,6 +28,16 @@ const api = createApi({ if (arg?.body && 'amount' in arg.body) { amount += 1 } + + if (arg?.body && 'forceError' in arg.body) { + return { + error: { + status: 500, + data: null, + }, + } + } + return { data: arg?.body ? { ...arg.body, ...(amount ? { amount } : {}) } @@ -813,8 +824,24 @@ describe('hooks tests', () => { const [errMsg, setErrMsg] = React.useState('') const [isAborted, setIsAborted] = React.useState(false) - const handleClick = () => { + const handleClick = async () => { const res = updateUser({ name: 'Banana' }) + + // no-op simply for clearer type assertions + res.then((result) => { + // currently passing with a false positive, because error is getting typed as `any` + expectExactType< + | { + error: { status: number; data: unknown } | SerializedError + } + | { + data: { + name: string + } + } + >(result) + }) + expectType<{ endpointName: string originalArgs: { name: string } From 3b56f579621cef8613ce9a3e873ccfebd0adc011 Mon Sep 17 00:00:00 2001 From: Shrugsy Date: Sat, 24 Apr 2021 19:53:24 +1000 Subject: [PATCH 04/11] temporarily suppress ts error --- src/query/tests/buildHooks.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/query/tests/buildHooks.test.tsx b/src/query/tests/buildHooks.test.tsx index 6aae2fcf6d..75c8b6c9af 100644 --- a/src/query/tests/buildHooks.test.tsx +++ b/src/query/tests/buildHooks.test.tsx @@ -839,6 +839,7 @@ describe('hooks tests', () => { name: string } } + // @ts-expect-error TEMPORARY ONLY - suppressed for codesandbox build >(result) }) From b377eb3c993bf7f3e78911be2527fdfdad7160be Mon Sep 17 00:00:00 2001 From: Shrugsy Date: Sat, 24 Apr 2021 20:00:13 +1000 Subject: [PATCH 05/11] Fix test failure --- src/query/tests/queryFn.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/query/tests/queryFn.test.tsx b/src/query/tests/queryFn.test.tsx index a1828e5bb3..969aa81741 100644 --- a/src/query/tests/queryFn.test.tsx +++ b/src/query/tests/queryFn.test.tsx @@ -247,7 +247,7 @@ describe('queryFn base implementation tests', () => { { const thunk = mutationWithNeither.initiate('mutationWithNeither') const result = await store.dispatch(thunk) - expect(result.error).toEqual( + expect(result!.error).toEqual( expect.objectContaining({ message: 'endpointDefinition.queryFn is not a function', }) From 1a44f222a08090006bbabd17132fbbb9e7896eab Mon Sep 17 00:00:00 2001 From: Shrugsy Date: Sat, 24 Apr 2021 20:09:32 +1000 Subject: [PATCH 06/11] Actually fix test failure --- src/query/tests/queryFn.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/query/tests/queryFn.test.tsx b/src/query/tests/queryFn.test.tsx index 969aa81741..67ac89dd8e 100644 --- a/src/query/tests/queryFn.test.tsx +++ b/src/query/tests/queryFn.test.tsx @@ -247,7 +247,7 @@ describe('queryFn base implementation tests', () => { { const thunk = mutationWithNeither.initiate('mutationWithNeither') const result = await store.dispatch(thunk) - expect(result!.error).toEqual( + expect((result as any).error).toEqual( expect.objectContaining({ message: 'endpointDefinition.queryFn is not a function', }) From d7e83f001fcf50427977f4d5f6f94b93b10a1c98 Mon Sep 17 00:00:00 2001 From: Shrugsy Date: Sat, 24 Apr 2021 20:54:59 +1000 Subject: [PATCH 07/11] Exclude BaseQueryError from being undefined in useMutation trigger resolve value --- src/query/core/buildInitiate.ts | 11 +++++++---- src/query/tests/buildHooks.test.tsx | 1 - 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/query/core/buildInitiate.ts b/src/query/core/buildInitiate.ts index 3f96ac3c63..986f3dfbe8 100644 --- a/src/query/core/buildInitiate.ts +++ b/src/query/core/buildInitiate.ts @@ -83,10 +83,13 @@ export type MutationActionCreatorResult< | { data: ResultTypeFrom } | { error: - | BaseQueryError< - D extends MutationDefinition - ? BaseQuery - : never + | Exclude< + BaseQueryError< + D extends MutationDefinition + ? BaseQuery + : never + >, + undefined > | SerializedError } diff --git a/src/query/tests/buildHooks.test.tsx b/src/query/tests/buildHooks.test.tsx index 75c8b6c9af..6aae2fcf6d 100644 --- a/src/query/tests/buildHooks.test.tsx +++ b/src/query/tests/buildHooks.test.tsx @@ -839,7 +839,6 @@ describe('hooks tests', () => { name: string } } - // @ts-expect-error TEMPORARY ONLY - suppressed for codesandbox build >(result) }) From 07a430b67bc49ac5709d598fcb0a62b69c82c2be Mon Sep 17 00:00:00 2001 From: Shrugsy Date: Sat, 24 Apr 2021 21:36:04 +1000 Subject: [PATCH 08/11] Misc changes to useMutation types/docblocks: - Fix promise result in pseudo-types on docs - Fix wording for 'abort' method docblock --- query-old/docs/api/created-api/hooks.md | 2 +- src/query/core/buildInitiate.ts | 3 ++- src/query/tests/buildHooks.test.tsx | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/query-old/docs/api/created-api/hooks.md b/query-old/docs/api/created-api/hooks.md index f369861829..fd0a41c413 100644 --- a/query-old/docs/api/created-api/hooks.md +++ b/query-old/docs/api/created-api/hooks.md @@ -95,7 +95,7 @@ type UseMutation = () => [UseMutationTrigger, UseMutatio type UseMutationTrigger = ( arg: ArgTypeFrom -) => Promise<{ data: ResultTypeFrom }> & { +) => Promise<{ data: ResultTypeFrom } | { error: BaseQueryError | SerializedError }> & { arg: { endpointName: string; // The name of the given endpoint for the mutation originalArgs: ArgTypeFrom; // Arguments passed to the mutation diff --git a/src/query/core/buildInitiate.ts b/src/query/core/buildInitiate.ts index 986f3dfbe8..3a6d7d7b0c 100644 --- a/src/query/core/buildInitiate.ts +++ b/src/query/core/buildInitiate.ts @@ -121,7 +121,8 @@ export type MutationActionCreatorResult< * A method to cancel the mutation promise. Note that this is not intended to prevent the mutation * that was fired off from reaching the server, but only to assist in handling the response. * - * Calling `abort()` prior to the promise resolving will make it throw with an error like: + * Calling `abort()` prior to the promise resolving will force it to reach the error state with + * the serialized error: * `{ name: 'AbortError', message: 'Aborted' }` * * @example diff --git a/src/query/tests/buildHooks.test.tsx b/src/query/tests/buildHooks.test.tsx index 6aae2fcf6d..5c5cc69a05 100644 --- a/src/query/tests/buildHooks.test.tsx +++ b/src/query/tests/buildHooks.test.tsx @@ -829,7 +829,6 @@ describe('hooks tests', () => { // no-op simply for clearer type assertions res.then((result) => { - // currently passing with a false positive, because error is getting typed as `any` expectExactType< | { error: { status: number; data: unknown } | SerializedError From b47b6fc1115deada9a5a04e38bf1954645ea1341 Mon Sep 17 00:00:00 2001 From: Shrugsy Date: Sat, 24 Apr 2021 22:06:31 +1000 Subject: [PATCH 09/11] Add missing `UseMutationStateOptions` to `UseMutation` pseudo type --- query-old/docs/api/created-api/hooks.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/query-old/docs/api/created-api/hooks.md b/query-old/docs/api/created-api/hooks.md index fd0a41c413..cc26921d3a 100644 --- a/query-old/docs/api/created-api/hooks.md +++ b/query-old/docs/api/created-api/hooks.md @@ -91,7 +91,14 @@ The query arg is used as a cache key. Changing the query arg will tell the hook #### Signature ```ts -type UseMutation = () => [UseMutationTrigger, UseMutationResult]; +type UseMutation = ( + UseMutationStateOptions +) => [UseMutationTrigger, UseMutationResult | SelectedUseMutationResult]; + +type UseMutationStateOptions = { + // A method to determine the contents of `UseMutationResult` + selectFromResult?: (state, defaultMutationStateSelector) => SelectedUseMutationResult extends Record +} type UseMutationTrigger = ( arg: ArgTypeFrom @@ -122,6 +129,16 @@ type UseMutationResult = { }; ``` +:::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. + +Passing a completely empty object will prevent the hook from causing a re-render at all, e.g. +```ts +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 From 66dd9bb1abd623d1cf43b756eafe3eb1cc085170 Mon Sep 17 00:00:00 2001 From: Shrugsy Date: Sat, 24 Apr 2021 22:14:12 +1000 Subject: [PATCH 10/11] Remove `arg` from the `UseMutationTrigger` docs signature --- query-old/docs/api/created-api/hooks.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/query-old/docs/api/created-api/hooks.md b/query-old/docs/api/created-api/hooks.md index cc26921d3a..d8b4017539 100644 --- a/query-old/docs/api/created-api/hooks.md +++ b/query-old/docs/api/created-api/hooks.md @@ -103,12 +103,6 @@ type UseMutationStateOptions = { type UseMutationTrigger = ( arg: ArgTypeFrom ) => Promise<{ data: ResultTypeFrom } | { error: BaseQueryError | SerializedError }> & { - arg: { - endpointName: string; // The name of the given endpoint for the mutation - originalArgs: ArgTypeFrom; // Arguments passed to the mutation - track?: boolean; // Whether the mutation is being tracked in the store - startedTimeStamp: number; // Timestamp for when the mutation was initiated - }; requestId: string; // A string generated by RTK Query abort: () => void; // A method to cancel the mutation promise unwrap: () => Promise>; // A method to unwrap the mutation call and provide the raw response/error From dc9fc32ec4153fa8fcbf5053de45f49f7e4a44b8 Mon Sep 17 00:00:00 2001 From: Shrugsy Date: Sun, 25 Apr 2021 02:45:19 +1000 Subject: [PATCH 11/11] Remove `as any` cast in altered test --- src/query/tests/queryFn.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/query/tests/queryFn.test.tsx b/src/query/tests/queryFn.test.tsx index 67ac89dd8e..1d4a73268f 100644 --- a/src/query/tests/queryFn.test.tsx +++ b/src/query/tests/queryFn.test.tsx @@ -247,7 +247,7 @@ describe('queryFn base implementation tests', () => { { const thunk = mutationWithNeither.initiate('mutationWithNeither') const result = await store.dispatch(thunk) - expect((result as any).error).toEqual( + expect('error' in result && result.error).toEqual( expect.objectContaining({ message: 'endpointDefinition.queryFn is not a function', })