Skip to content

Typed Queries & Mutations

This guide explains how to use TypeScript to ensure type safety when executing GraphQL queries and mutations in the Bagisto Headless storefront.

Overview

The storefront leverages TypeScript's powerful type inference and generic interfaces to provide end-to-end type safety. This ensures that the data sent to the API and the responses received are always validated against pre-defined interfaces, reducing runtime errors and improving developer productivity.

1. Defining Input Interfaces

Before executing a query or mutation, define the shape of the data required by the API. This is usually done using interfaces that match the GraphQL input types.

Example: Shipping Method Input

typescript
interface saveShippingMethodsTypes {
  token: string;
  shippingMethod: string;
}

2. Typing API Requests

The fetchHandler utility is designed to handle API requests. While it is generic, you can provide it with specific types to ensure the body payload is correct.

Internal Type: src/utils/fetch-handler.ts

typescript
interface FetchHandlerOptions<TBody = unknown> {
  url: string;
  method?: Method;
  body?: TBody; // Typed payload
  // ...
}

3. Using Generic Mutations

When using useMutation from @tanstack/react-query, you can pass your input interfaces to the mutation function. This provides autocomplete and linting errors if you pass incorrect data.

File: src/utils/hooks/useCheckout.ts

typescript
const { mutateAsync: saveShipping } = useMutation({
  mutationFn: (data: saveShippingMethodsTypes) => // Explicitly typed input
    fetchHandler({
      url: "checkout/saveShipping",
      method: "POST",
      body: data,
    }),
});

4. Handling Typed Responses

Since API responses can vary, the storefront often uses type casting or guards to handle the returned data safely.

typescript
const { data } = useQuery({
  queryKey: ["cart", token],
  queryFn: async () => {
    const response = await fetchHandler({ url: "cart/getCart", ... });
    return response.data as BagistoCart; // Casting to a known interface
  }
});

5. Benefits of Typed Operations

  • Early Error Detection: TypeScript will flag if you are missing a required field (like token) before you even run the code.
  • Improved Autocomplete: IDEs can provide suggestions for the response data (e.g., data.grandTotal), making development faster.
  • Refactoring Safety: If the GraphQL schema changes, you only need to update the interface in one place to see all affected parts of the application.

Next Steps

Released under the MIT License.