Of course, you should be able to type your content quickly! (ssr)

Written by Knut Melvær

Missing Image!

TypeScript brings "type safety" to JavaScript and has gained popularity over the past ten years. We see the adoption, especially with teams shipping business-critical web experiences to production. TypeScript makes it easier to identify errors and enables a vast array of convenient tooling that makes work easier, faster, and less error-prone for developers.

For a content platform specializing in making content available as data for developers, providing excellent support for TypeScript makes total sense. That's why we haven't settled on recommending GraphQL Codegen (which is still a viable option!). We wanted to bring full TypeScript support for Sanity Content Lake data queried with GROQ, the most flexible query language for JSON documents.

We have launched the beta version of our official TypeScript for content support: Sanity TypeGen. Upgrading your Sanity CLI allows you to generate TypeScript types from your Sanity Studio schema and GROQ query results in your web application.

This will enable you to build with the great developer experience that TypeScript offers without compromising the flexibility of GROQ and expressive content models for Sanity Studio.

We are releasing our official TypeScript support in beta because we wish to learn more about how you want to use this and what edge cases to cover. That being said, we believe most projects using TypeScript will benefit from this tooling today.

# Upgrade to the latest version of `sanity`
npm install sanity@latest

# Exctract a static representation of the schema
npx sanity schema extract

# Generate types from schema and GROQ queries
npx sanity typegen generate

Learn more:

You can give us feedback in the #typescript channel in the Sanity community or to your customer success channel.

PortableText [components.type] is missing "muxVideo2"

Worth the wait

Official support for typed Sanity content has been a popular feature request. And it makes sense! If you have done the work of defining your content model as code, it makes sense that you don’t want to do this work again in your front end. We have felt this pain internally, too.

We faced three challenges going into this project:

  1. A schema for a Sanity Studio workspace is defined and compiled in JavaScript (not a static data format like JSON). So, it’s not straightforward to create a static representation of it.
  2. One thing is to translate the schema to TypeScript types, but most projects use GROQ (or GraphQL) to query the documents created from it. GROQ allows you to combine content types and reshape the returned data. In other words, types generated from the schema would quickly stop being useful if you use GROQ beyond simple queries.
  3. For such a foundational feature, there were also many choices to make regarding the API design and developer experience. We learned from customers and the community and evaluated exciting community projects. We wanted to launch this with great confidence that we have chosen the right path for future query tooling improvements.

How we got there

We have now taken learnings from early exploration (especially sanity-codegen), and community projects (we’ll return to those after this post) and devised a solution we believe can set the path forward.

For us, it was vital that the type generation could scale in terms of performance (some projects have many schema types, and their queries are plenty and complex). Another important goal was that we didn’t compromise on the value of expressive content modeling and the flexibility of GROQ.

While real-time type generation is great, it proved challenging to scale. We also saw that code generation as a build step was how most similar projects approached this, so we took this as validation.

Speaking of community projects.

A huge thank you to the community!

It shouldn’t go amiss that the community has been at the forefront of figuring out how the Sanity and TypeScript story should be. We have been amazed by the efforts, and even though we’re now releasing the “official solution,” we hope it doesn’t take away from the value and effort put into these projects.

sanity-codegen

One of the first efforts to solve the challenge of TypeScript was the sanity-codegen package developed by Rico Kahler for Sanity Studio v2. Eventually, we were lucky enough to hire Rico as an engineer for the Sanity team. Unfortunately, we had to de-prioritize this work to ship Sanity Studio v3, a complete rewrite of the Studio and its APIs. Rico’s effort and insight have been and still are essential for our work on TypeScript code generation.

GROQD

We were impressed when Nearform (formerly known as Formidable) launched their Zod-powered GROQD package, which gives you runtime type validation for GROQ queries through the Zod-like query builder. If this is your preferred approach, we hope our new tooling for schema extractions can simplify the heavy lifting for projects like this.

sanity-typed

It has been a privilege to follow Shayan Hashimoto’s journey with the sanity-typed suite, which offers a range of TypeScript tooling for Sanity content. What’s unique about the sanity-typed project is that the implementation is done with TypeScript types (cue Inception soundtrack) to obtain real-time type generation. This is no small feat. It’s tough to pull off.

We also love how Shayan has made the developer experience footprint minimal by conforming with the Studio APIs, allowing you to switch out the dependency to get value.

A group of people watching a presentation called "Sanity, TypeScript, & You"

New to TypeScript? Check out our new course!

TypeScript is definitively here to stay, and we see it being used increasingly in teams and among professional developers. But it’s not like everyone uses TypeScript or has learned it yet.

Exploring our new TypeScript tooling and following the step-by-step guide on Sanity Learn can be an excellent way to start learning. You will also find recommendations for other TypeScript learning materials in the course.