Discussion on generating types for Sanity Client and alternatives

22 replies
Last updated: Feb 23, 2024
There something like this https://the-guild.dev/graphql/codegen for Sanity Client? I have my
/frontend
dir next to my
/backend
dir in a repo though so is the technique to move up the directory tree and import types from my
/backend
?
AI Update

Yes! Sanity has an official type generation tool called TypeGen that works similarly to GraphQL Codegen. It generates TypeScript types from both your schema and your GROQ queries.

For your monorepo setup with /frontend and /backend directories, you have a couple of good options:

Option 1: Generate types in backend, output to frontend

You can configure TypeGen to scan your frontend code and generate types directly into your frontend directory. Create a sanity-typegen.json configuration file in your /backend directory:

{
  "path": "../frontend/src/**/*.{ts,tsx,js,jsx}",
  "schema": "./schema.json",
  "generates": "../frontend/src/sanity/types.ts"
}

Then run from your backend directory:

npx sanity@latest schema extract
npx sanity@latest typegen generate

This will:

  1. Extract your schema to schema.json
  2. Scan your frontend code for GROQ queries (wrapped in defineQuery)
  3. Generate types directly into your frontend directory at the specified path

Option 2: Import types from backend

If you prefer to generate types in /backend and import them, that works perfectly:

// In your frontend
import type { Post, Author } from '../backend/sanity.types'

Just make sure your TypeScript config allows this with appropriate path mappings or relative imports.

How it works

The TypeGen workflow generates types for:

  • All your schema types
  • GROQ query results (when you use defineQuery)
  • Built-in Sanity types

For GROQ queries, wrap them with defineQuery to get type inference:

import { defineQuery } from 'next-sanity' // or 'groq'

const POSTS_QUERY = defineQuery(`*[_type == "post"]{title, slug}`)
const posts = await client.fetch(POSTS_QUERY) // fully typed as POSTS_QUERYResult!

The defineQuery helper enables automatic type inference when using Sanity Client, so you don't need to manually specify types.

Re-run npx sanity typegen generate whenever you modify your schema or queries to keep types synchronized.

Does this work if you’re not self-hosting studio?
It looks like this infers types from the definitions in studio schema. However I don’t have studio nested in my frontend so when I deploy my next project this wont work because it wont have access to the backend directory.
Yeah, I have the same issue. It would be nice to dump the schema into a singles file through codegen and easely copy and paste it into the frontend, but I'm nut sure how to handle all that at the moment.
There is
ts-simplify
which you can use to get the "simple" types into a file, which you could copy/paste.
Thank you man
i’ll try that out thanks!
Probably a typo, you’re referring to this one https://www.npmjs.com/package/simplify-ts ?
How can i handle this?

const VARIANTS = [
  { title: 'Simple', value: undefined },
  { title: 'Caption', value: 'caption' as const },
  { title: 'Call to action', value: 'callToAction' as const },
  { title: 'Product hotspots', value: 'productHotspots' as const },
  { title: 'Product tags', value: 'productTags' as const },
]
i got my types generating on dev and build now though
 "scripts": {
    "dev": "sanity dev && npm run generate-types",
    "start": "sanity start",
    "build": "sanity build && npm run generate-types",
    "deploy": "sanity deploy",
    "deploy-graphql": "sanity graphql deploy",
    "generate-types": "npx ts-simplify ./sanity.config.ts ../frontend/types/sanity.d.ts -f"
  },
undefined
shouldn't be a valid value under your
"Simple"
option.
It’s from https://github.com/sanity-io/sanity-shopify-studio studio starter. Lemme try and understand why they did that.
not many TS errors for this big project though, but my TS isn’t up to snuff quite yet. Trying to figure out this one atm.
interface ColorOption {
  title: string
}
https://www.sanity.io/docs/reference/api/sanity/TemplateFieldDefinition not sure if this is where i should be looking but I do see
options?: {
  [key: string]: any
}
I thought I was generating types at first turns out it was only generating a few types and I had too many errors so I went back to manual typing. I’ll come back to it later and potentially use another method
user L
Ok. I switched to graphql, it's pretty easy to add typescript codegen based on the queries. I can share the code if you still want to have a typed client.
Switching to graphql doesn’t seem minor tho. Do you still get the same ease with joining references like you do with groq? And then for your visualizer what is the alternative to the Vision plugin?
i use graphql for lots of other projects though so i have no aversion to it. Just curious how the experience is with sanity.
Sorry for the late answer.It's not a minor change, but in my case I was at the begging of the project. I mistakenly assumed it was the case for you as well.

Do you still get the same ease with joining references like you do with groq?
I don't have enough nested content to answer this with confidence, but I think you can query nested references easily. Let me know if that's not what you were asking.

And then for your visualizer what is the alternative to the Vision plugin?
You have a graphql playground similar to the vision tab. And it has schema introspection.

Just curious how the experience is with sanity.
I understand, in my opinion it's really worth the effort.
I can share my project playground link if you want. It has no sensitive data on it. And it's hosted on sanity.io domain.

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?