--- title: Sanity TypeGen Rules description: Workflow for generating TypeScript types from Sanity Schema and GROQ queries. --- # Sanity TypeGen Rules ## 1. The Workflow Sanity TypeGen generates TypeScript types from your schema and GROQ queries. Types can be generated automatically or manually. ### Automatic (Recommended) Enable in `sanity.cli.ts` — types regenerate during `sanity dev` and `sanity build`: ```typescript // sanity.cli.ts import { defineCliConfig } from 'sanity/cli' export default defineCliConfig({ typegen: { enabled: true, }, }) ``` ### Manual Run the extract + generate cycle whenever schema or queries change: 1. **Extract:** Converts your Schema (TS/JS) into a static JSON representation. 2. **Generate:** Scans your codebase for GROQ queries and generates TypeScript types. ```bash npx sanity schemas extract --force && npx sanity typegen generate ``` ### Watch Mode (for separate frontends) If your frontend is in a separate repo from the Studio, use watch mode: ```bash npx sanity typegen generate --watch ``` ## 2. The "Update Types" Pattern For manual workflows, implement a single script: **package.json:** ```json "scripts": { "typegen": "sanity schemas extract --force && sanity typegen generate" } ``` ### Git Strategy for Generated Files **Option A: Commit generated types (Recommended for most teams)** - Types available immediately after `git pull` - CI/CD doesn't need to run typegen - Can cause merge conflicts **Option B: Generate in CI (Recommended for larger teams)** Add to `.gitignore`: ```gitignore # Sanity TypeGen (generated) sanity.types.ts schema.json ``` Then ensure CI runs typegen before build: ```yaml # Example GitHub Actions - run: npm run typegen - run: npm run build ``` ## 3. Configuration (`sanity.cli.ts`) > **Note:** `sanity-typegen.json` is deprecated. Move your configuration to `sanity.cli.ts`. ```typescript // sanity.cli.ts import { defineCliConfig } from 'sanity/cli' export default defineCliConfig({ typegen: { enabled: true, // Auto-generate during sanity dev/build path: "./src/**/*.{ts,tsx,js,jsx,astro,svelte,vue}", // Glob to find queries schema: "schema.json", // Schema file from extract generates: "./sanity.types.ts", // Output file overloadClientMethods: true, // Auto-type client.fetch() calls }, }) ``` ### Project Structure Examples **Monorepo (recommended)** (Studio in `studio/`, Frontend in `web/` — same config works under `apps/`): ```typescript export default defineCliConfig({ typegen: { path: "../web/src/**/*.{ts,tsx,js,jsx}", schema: "schema.json", generates: "../web/sanity.types.ts", }, }) ``` **Single Repo / Embedded Studio (legacy):** Use defaults — no extra config needed. **Separate Repos:** Use `--watch` mode in your frontend: `sanity typegen generate --watch` ## 4. Usage in Code ### Automatic Type Inference (Recommended) With `overloadClientMethods: true` (default), `client.fetch()` automatically returns typed results when you use `defineQuery`: ```typescript import { defineQuery } from "groq"; import { createClient } from "@sanity/client"; const client = createClient({...}); const POSTS_QUERY = defineQuery(`*[_type == "post"]{ title, slug }`); // Return type is automatically inferred — no manual type import needed! const posts = await client.fetch(POSTS_QUERY); ``` ### Manual Type Import (Alternative) You can also import generated types directly: ```typescript import { defineQuery } from "groq"; // Next.js re-exports defineQuery for convenience: // import { defineQuery } from "next-sanity"; const AUTHOR_QUERY = defineQuery(`*[_type == "author" && slug.current == $slug][0]{ name, bio }`); import type { AUTHOR_QUERY_RESULT } from "@/sanity.types"; export default function Author({ data }: { data: AUTHOR_QUERY_RESULT }) { return