typescriptredux-toolkitrtk-query

Which is in Redux Toolkit the type of a `builder.mutation` return value?


I've setup my Redux-Toolkit in my Nextjs application.

I've a mutation, setup like this:

postCar: builder.mutation<Car, CarEndpointPostParams>({
  query: ({ body = {} }) => ({
    url: "/api/cars",
    method: "POST",
    body,
  }),
}),

And this mutation is exported as usePostCarMutation

In one of my component, AddCar.tsx I am using this generated Redux-Toolkit hook:

const [postCar, result] = usePostCarMutation();

This postCar is provided to a child component, AddCarForm.tsx as a property.

I am trying to understand which is the type of the prop postCar of AddCarForm.tsx, unsuccessfully.

ATTEMPT 1

postCar: typeof api.endpoints.postCar

ATTEMPT 2

postCar: MutationDefinition<
  Car,
  BaseQueryFn,
  any,
  CarEndpointPostParams,
  any
>

ATTEMPT 3

postCar: MutationTrigger<MutationDefinition<
  Car,
  BaseQueryFn,
  any,
  CarEndpointPostParams,
  any
>>

Any ideas?


Solution

  • I am trying to understand which is the type of the prop postCar of AddCarForm.tsx

    The useMutation hook is typed as follows:

    type UseMutation = (
      options?: UseMutationStateOptions,
    ) => [UseMutationTrigger, UseMutationResult | SelectedUseMutationResult]
    

    Your postCar trigger function is type UserMutationTrigger:

    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
      reset: () => void // A method to manually unsubscribe from the mutation call and reset the result to the uninitialized state
    }
    

    Where T is the return type you specified in the endpoint, e.g. Car, so it results in a postCar type that looks like this:

    type UseMutationTrigger<Car> = (arg: any) => Promise<
      { data: Car } | { error: BaseQueryError | SerializedError }
    
    > & {
      requestId: string
      abort: () => void
      unwrap: () => Promise<Car>
      reset: () => void
    }
    

    This postCar is provided to a child component, AddCarForm.tsx as a property.

    A postCar prop type would be something like: postCar: UseMutationTrigger<Car> in any consuming component.

    There is a TypedMutationTrigger type you can use:

    import { TypedMutationTrigger } from "@reduxjs/toolkit/dist/query/react";
    
    export type PostCarTriggerFn = TypedMutationTrigger<
      Car,
      CarEndpointPostParams,
      any
    >;
    

    Or you can get it from the usePostCarMutation hook's return type:

    export type PostCarTriggerFn = ReturnType<typeof usePostCarMutation>[0];
    

    Type the postCar prop:

    postCar: PostCarTriggerFn;
    

    Note/Recommendation

    Doing this goes a bit against the design-philosophy of Redux and RTK. Instead of passing the postCar trigger function down as props to children components, they should instead also just use the generated usePostCarMutation hook and access their own "copy" of the postCar trigger function. RTK and RTK-Query will cache results based on the args passed to the mutation, and return cached results. If two components make the same mutation request, i.e. same args, they see the same results.