Generating types

Thanks to Sanity TypeGen, the schema types in your Studio and the response shape of your GROQ queries can be fully typed.
There's a few steps involved to make this happen:
- Export the Studio schema configuration to a JSON file
- Configure Sanity TypeGen to look through your application to look for GROQ queries that use the
defineQuery
helper function - Generate Types from both the schema export and GROQ queries
apps/studio
directory to extract the Studio schema# in apps/studiopnpm dlx sanity@latest schema extract
You should now have a schema.json
file in the root of your apps/studio
directory.
apps/studio
directory for TypeGen to use this extract schema and search the Next.js project for queries{ "path": "../web/src/**/*.{ts,tsx,js,jsx}", "schema": "./schema.json", "generates": "../web/src/sanity/types.ts"}
apps/studio
directory to generate Types# in apps/studiopnpm dlx sanity@latest typegen generate
In the terminal you should see a message similar to the following:
✅ Generated TypeScript types for 14 schema types and 2 GROQ queries in 2 files into: ../web/src/sanity/types.ts
And you should also have a new file apps/web/src/sanity/types.ts
file inside your Next.js project.
While you could now manually use Types throughout the Next.js application, Sanity Client supports "automatic type inference." That is, the response of a query should be automatically typed.
If you open apps/web/src/sanity/types.ts
and scroll to the bottom, you will see something like the following
// ...all schema types
// Query TypeMapimport "@sanity/client";declare module "@sanity/client" { interface SanityQueries { '*[\n _type == "event" &&\n slug.current == $slug\n ][0]{\n ...,\n "date": coalesce(date, now()),\n "doorsOpen": coalesce(doorsOpen, 0),\n headline->,\n venue->\n}': EVENT_QUERYResult; '*[\n _type == "event"\n && defined(slug.current)\n && date > now()\n]|order(date asc){_id, name, slug, date}': EVENTS_QUERYResult; }}
As you add more queries to your application and re-run TypeGen, this automatic mapping between queries and responses will be updated.
You may notice there are red squiggly lines beneath @sanity/client
. Because these types extend that dependency, automatic type inference will not work until it is installed as a dependency.
@sanity/client
# in apps/webpnpm add @sanity/client -D
All the "redlines" from TypeScript in your route files should now be gone.
You should also see that the response from sanityFetch
in the home and individual page routes are typed.
You'll need to re-run the schema extraction and type generation every time you add or update Sanity Studio schema types or GROQ queries in your Next.js application.
To simplify this process, a common pattern is to run both from a single typegen
command
package.json
file to add the three lines to the scripts
section"scripts": { // ...the rest of your scripts "predev": "pnpm run typegen --enforce-required-fields", "prebuild": "pnpm run typegen --enforce-required-fields", "typegen": "sanity schema extract && sanity typegen generate --enforce-required-fields" // 👆 add these three lines},
--enforce-required-fields
flag will apply any rule.required()
logic in our Sanity Studio schema types to the generated types.# in apps/studiopnpm run typegen
You should see a confirmation that both processes have run successfully.
Don't forget to re-run this process every time you add or update Studio schema types or GROQ queries in your Next.js application.
You've now laid the groundwork for a Sanity Studio for your content backend and a Next.js front end with Types. This is a great start for most use cases!
As projects mature, parts of your foundation will likely need to change. This is where the next course, Handling schema changes confidently, can help you update schema types and configuration without downtime.
If you have the time, complete that course next, otherwise let's move onward to building content applications.