Migrate from experimental TypeGen in the App SDK

Upgrade an App SDK app from the deprecated experimental TypeGen packages to released groq and typegen.resources.

Before App SDK 3.9.0, TypeGen support for the App SDK came from experimental builds of @sanity/cli and groq (versions such as 3.88.1-typegen-experimental.0, configured with unstable_schemas in sanity-typegen.json). Those builds are deprecated. The current workflow uses typegen.resources in sanity.cli.ts, described in App SDK and TypeGen.

This guide covers two stages. The first keeps your saved sanity.types.ts working on released packages, so you can upgrade without changing your types. The second moves the app to typegen.resources, which you need before you can change schemas or queries again.

Prerequisites

  • @sanity/sdk-react and @sanity/sdk 3.9.0 or later.
  • groq 6.15.0 or later.
  • @sanity/cli 8.16.0 or later, to move to typegen.resources.

Keep the saved types file working

A sanity.types.ts generated by the experimental packages imports helper types such as SchemaOrigin from groq. App SDK 3.9.0 and later supply compatibility declarations for those imports, so the saved file keeps working with released groq while you migrate.

  • Keep a copy of your existing sanity.types.ts. Stop any install or build script that regenerates it with the experimental CLI, such as a typegen script that runs ./node_modules/@sanity/cli/bin/sanity typegen generate.
  • Replace the experimental groq dependency with released groq: npm install groq@^6.15.0. If you added a "groq": "$groq" entry to overrides for the experimental setup, it now resolves to the released version.
  • Remove the experimental @sanity/cli dependency, including any alias you used to install it beside the current CLI.
  • Import defineProjection from an App SDK package instead of groq: change import {defineProjection} from 'groq' to import {defineProjection} from '@sanity/sdk-react' (or @sanity/sdk). defineQuery still comes from groq. Keep existing query and projection strings unchanged, so they match the entries in your saved file.
  • Check your dependency tree and type-check the app:
npm ls groq
npx tsc --noEmit

Your generated file and the SDK must resolve the same released groq declarations. When they don't, TypeScript reports errors such as Module '"groq"' has no exported member 'SchemaOrigin' in the saved file, and hook results are typed as never (for example, Property 'title' does not exist on type 'never'). To fix this, align the app and SDK versions and update the lockfile. Keeping the experimental groq build alongside released groq isn't supported.

The saved file doesn't update. To change schemas or queries, move to typegen.resources.

Move to per-dataset types with typegen.resources

Make this move in one change, so old and new type registrations don't exist side by side:

  • Install @sanity/cli 8.16.0 or later, and configure each dataset under typegen.resources as described in App SDK and TypeGen.
  • Check which CLI version runs: npx sanity --version. The sanity package depends on @sanity/cli, and your lockfile can still resolve an older version. A CLI earlier than 8.16.0 ignores typegen.resources and fails with Schema file not found: …/schema.json - did you run "sanity schema extract"? If it reports an earlier version, run npm install --save-dev @sanity/cli@^8.16.0.
  • Add the document type as the first argument to each defineProjection call, as in defineProjection('book', '{title}'). Keep the query and projection text otherwise unchanged.
  • Delete sanity-typegen.json. While it exists, the CLI still uses sanity.cli.ts, but first warns You've specified typegen in your Sanity CLI config, but also have a typegen config.
  • Run npx sanity typegen generate.
  • Delete the saved sanity.types.ts, or remove the saved file from your TypeScript program. While both files exist, a handle without a literal dataset gets the union of the old and new types.
  • Update imports of generated types to the file for each dataset. A type that the old file shared across datasets becomes one export per file.
  • Type-check the app, and check the screens that read documents, run queries, and show projections.

Troubleshoot the migration

These errors can appear when you run npx sanity typegen generate after moving to per-dataset types:

  • Schema file not found: …/schema.json - did you run "sanity schema extract"?: The CLI that runs is earlier than 8.16.0, so it ignores typegen.resources. Check the version with npx sanity --version, and install a newer CLI with npm install --save-dev @sanity/cli@^8.16.0.
  • No schema is bound to dataset: The resource has no schema file, and the CLI couldn't fetch a bound schema for the dataset. Check the resource's projectId and dataset, or extract the schema with npx sanity schema extract and set schema on that resource.
  • Duplicate query name found: Two scanned files define a query with the same variable name. Query names must be unique across all scanned files, so rename one of them.

Next steps

Was this page helpful?

sanity.ioAll Systems Operational© Sanity 2026
Change site theme