Level up Shopify GraphQL API queries in Typescript

Shopify offers a robust GraphQL API that accommodates a broad spectrum of applications. However, in Typescript land it can be a bit tricky to get types right. Traditionally, this is accomplished with tools like graphql-codegen, which generate types for your queries. I’ve always found these tools cumbersome and you had to run a separate command to generate types.

Enter gql.tada, a tool I discovered from a Matt Pocock video, which I highly recommend watching. This tool generates types for your queries dynamically, along with several other quality-of-life enhancements. It significantly improves the developer experience when working with GraphQL.

Configure gql.tada with Shopify GraphQL API

To set up gql.tada in your project, follow the official documentation. The process is straightforward and involves adding a ts plugin. Initially, I got stuck finding the schema url for Shopify’s Admin API. However, I eventually found a Shopify Remix App Guide that led me to the solution.

tsconfig.json
{
"plugins": [
{
"name": "@0no-co/graphqlsp",
"tadaOutputLocation": "./src/graphql-env.d.ts",
// Schema for Shopify Admin API
// Version should match the api version you are using in client
"schema": "https://shopify.dev/admin-graphql-direct-proxy/2024-01"
}
]
}

Make sure your code editor is using the correct Typescript version. To do this, open your command palette (Ctrl + Shift + P) and select TypeScript: Select TypeScript Version. You might need to open a TypeScript file first to see this option. Choose the “Workspace Version.”

At this point, you should be able to see the types generated by gql.tada in the src/graphql-env.d.ts file. Tada!

Using urql to query Shopify GraphQL API

gql.tada supports several client libraries, including urql. I opted for urql because it’s a lightweight client, specifically the @urql/core package. You’ll need to create a Shopify app and obtain the access token and URL for your store. Keep in mind that the API versions should correspond to the schema version you specified in tsconfig.json.

Here’s a helper function to create a client for Shopify’s Admin API:

import { Client, cacheExchange, fetchExchange } from "@urql/core"
export function createShopifyClient(config: { url: string; accessToken: string }) {
return new Client({
url: config.url, // https://{store}.myshopify.com/admin/api/2024-01/graphql.json
exchanges: [cacheExchange, fetchExchange],
fetchOptions: () => {
return {
headers: { "X-Shopify-Access-Token": config.accessToken }, // shpat_xxx
}
},
})
}

Let’s execute a simple query to retrieve details about the store.

import { graphql } from "gql.tada"
const shop = createShopifyClient({
url: env.SHOPIFY_ADMIN_API_URL,
accessToken: env.SHOPIFY_ADMIN_ACCESS_TOKEN,
})
const result = await shop.query(
graphql(`
query GetShop {
shop {
name
primaryDomain {
url
host
}
}
}
`),
{}
)
console.log("shop", result.data?.shop.name)

At this point, you should be able to see the generated types in action. If you attempt to access a field that doesn’t exist in the query, you’ll receive a TypeScript error. It also identifies unused fields in the query and warns you about them. Hover over any field to see the type definition, complete with information that provides additional context by the schema.

Shopify GraphQL LSP

I also installed the GraphQL extension for VSCode, which provides syntax highlighting. However, I noticed some bugs that cause the syntax highlighting to break for the rest of the file. Hopefully these issues will be fixed in future updates.

The library also offers a bunch other features not covered in this post. I highly recommend using it if you work with GraphQL in Typescript.