Sanity Pioneers — Join builders from Complex, Amplitude & Airtable in San Francisco, March 19

Sanity TypeGen is now generally available

TypeGen generates exact TypeScript types from your schemas and queries. So AI tools stop guessing and developers stop debugging phantom fields.

  • Kristoffer Brabrand

    Senior Software Engineer

  • Sindre Gulseth

    Staff Software Engineer

  • Knut Melvær

    Principal Developer Marketing Manager

Published

AI coding tools are only as good as the context you give them. Point Claude, Cursor, or Copilot at vague, or no, types and you get vague suggestions. Give them precise types and they autocomplete correctly, catch edge cases, and stop hallucinating field names.

Sanity TypeGen generates precise TypeScript types from your content schemas and GROQ queries. Which means that you (and your agents) get the most out of the flexbility of GROQ, without losing the power of a well-defined schema. Few, if any, CMSes out there give you this developer experience.

So instead of event.format: string, you get 'in-person' | 'virtual'. Instead of post.coverImage: any, you get the full image structure with asset reference and optional alt text. Your editor autocompletes GROQ projections. Your AI assistant stops inventing fields (🤞). Your types stay in sync with your content model.

TypeGen is now generally available in Sanity Studio v5 with automatic regeneration, consolidated configuration, and stable APIs. If you used the beta, the migration is straightforward, the breaking changes are intentional improvements that make generated types more accurate.

Types that stay in sync while coding

The most requested feature during the beta was automation. Manually running sanity schema extract and sanity typegen generate every time you changed a schema or query worked, but it was easy to forget and end up with stale types.

Now you can turn on automatic type generation with a single config option. When you enable typegen.enabled: true, TypeGen will run automatically during sanity dev:

// sanity.cli.ts
import { defineCliConfig } from 'sanity/cli'

export default defineCliConfig({
  // …your project config
  typegen: {
    enabled: true,
  },
})

Running sanity dev now watches your schema and query files automatically. If you're running a separate frontend repo, use the --watch flag:

sanity typegen generate --watch

One config file, not two

TypeGen originally had sanity-typegen.json for configuration. Now everything lives in sanity.cli.ts alongside your other CLI settings.

// sanity.cli.ts
import { defineCliConfig } from 'sanity/cli'

export default defineCliConfig({
  // …your project config
  typegen: {
    enabled: true,
    path: './sanity.types.ts',
    schema: './schema.json',
    generates: {
      './src/types.ts': {
        // custom generation options
      },
    },
    overloadClientMethods: true,
  },
})

The old config file still works but now shows a deprecation warning.

One caveat: if you’re in a mono repo where the studio and other apps are in different packages, you'll still need the JSON schema for those:

  • Enable schemaExtraction.enabled: true in the studio's sanity.cli.ts to produce the schema.json.

  • Then point your frontend/apps repo's typegen config at that generated schema file.

Faster generation (with a progress bar, finally)

We rewrote the type generation internals with memoization, so updates in watch mode are significantly faster. You'll also see a progress indicator during generation so you know it's working. (No, we can’t promise we have finaly solved the halting problem.)

Smarter generated output

The generated types are now more accurate and easier to work with:

  • Preserved casing: A query named MyPageQuery now produces MyPageQueryResult instead of MypagequeryResult
  • Correct non-identifier keys: Fields with kebab-case or special characters are now properly quoted
// Before
type Post = {
  my-field: string  // ❌ Invalid TypeScript
}

// After
type Post = {
  'my-field': string  // ✅ Properly quoted
}
  • Smaller output: Array types now use an ArrayOf utility type, reducing duplication and file size

Type utilities for real-world schemas

Two new utility types make it easier to work with complex content models. This is especially handy for landing page-type content that tends to get nested.

The Get utility extracts deeply nested properties (up to 20 levels):

import type { Get } from '@sanity/codegen'
import type { Page } from './sanity.types'

// Extract a deeply nested type
type HeroSection = Get<Page, 'sections', number, 'hero'>

// No more juggling NonNullable and index access
type OldWay = NonNullable<NonNullable<NonNullable<Page>['sections']>[number]>['hero']

The FilterByType utility pulls specific types from unions using the _type discriminator:

import type { FilterByType } from '@sanity/codegen'
import type { PageBuilder } from './sanity.types'

// Extract only hero blocks from a union of block types
type HeroBlock = FilterByType<PageBuilder, 'hero'>

// Works with multiple types too
type ContentBlocks = FilterByType<PageBuilder, 'hero' | 'textBlock' | 'imageGallery'>

Framework support beyond Next.js

The TypeGen tooling now supports @sanity/sveltekit defineQuery imports and can parse .svelte and .vue files. Support for .astro files was already available.

What “GA” means (and what it doesn't)

General availability means the TypeGen APIs are stable. The configuration format, CLI commands, and utility types won't change in breaking ways. Generated output will continue to improve, but those improvements will remain compatible with your existing code.

Some limitations remain:

Getting started

Setup depends on your project structure. Here are the three most common scenarios:

If you're running sanity dev or sanity build in your studio

In your studio, you typically want schema extraction enabled to generate the schema.json file. If you only need the schema.json (for example, to use in other packages), enable schemaExtraction.enabled: true. If you also need types in your studio code (for custom components, etc.), add typegen.enabled: true as well. Both control whether these processes run as part of sanity dev and sanity build commands.

// sanity.cli.ts
import { defineCliConfig } from 'sanity/cli'

export default defineCliConfig({
  // …your project config
  schemaExtraction: {
    enabled: true,
  },
  typegen: {
    enabled: true,
  },
})

Monorepo with separate studio and frontend packages

In your studio's sanity.cli.ts, enable schemaExtraction.enabled: true to generate the schema.json file when you run sanity dev or sanity build. Add typegen.enabled: true if you also want to generate types for use in the studio itself.

In your frontend packages, run sanity typegen generate --watch and configure the path to point to the schema.json generated by the studio. Since frontend repos don't use sanity dev or sanity build, you run the typegen command directly with the --watch flag for automatic regeneration during development.

Studio embedded in another app

If your Studio is embedded on an app route (Next.js, Astro, Nuxt, etc.), you're not using sanity dev or sanity build to build your app. This means the enabled flags won't help you. Instead, you'll need to run the CLI commands directly:

  • sanity schema extract to generate the schema JSON
  • sanity typegen generate to create types (use --watch for automatic regeneration during development)

Migrating from the beta

If you're using the beta, here's the migration path:

  1. Update to Sanity Studio v5
  2. Move config from sanity-typegen.json to sanity.cli.ts
  3. Regenerate types (expect diffs due to improvements)
  4. Enable automatic generation with enabled: true

The breaking changes are intentional corrections that make the generated types more accurate.

Everything that changed since beta

Here’s the smørgåsbord of most of the things we improved:

  • Automatic type generation during sanity dev and sanity build
  • Configuration moved to sanity.cli.ts
  • Progress indicator during generation
  • Memoization for faster watch mode updates
  • Preserved casing in generated type names
  • Proper quoting for non-identifier keys
  • ArrayOf utility type for smaller output
  • Get utility for extracting nested types (up to 20 levels)
  • FilterByType utility for filtering union types
  • Support for @sanity/sveltekit defineQuery
  • Parsing support for .svelte and .vue files
  • @sanity-typegen-ignore comment support
  • Stable API surface (no more breaking changes planned)

The Sanity Learn course has been updated to reflect all these changes. If you're new to TypeGen or want to see the latest features in action, it's a great place to start.

Thanks to Kristoffer Brabrand, Rico Kahler, and Sindre Gulseth for the work here. And to everyone who tested the beta and provided feedback. If you run into issues or have suggestions, join us in the #typescript channel in the Sanity community Discord.