Generated types are a contract, not a convenience
Types written by hand describe what you believed the schema said. Types generated from it describe what the schema actually says.

A hand-written interface for a CMS document is a snapshot of an assumption. It was accurate when it was written and it is accurate now only if nobody has touched the schema since — which is not a property you can check.
Regenerate rather than remember
Generation turns the schema into the single source of truth, and makes every mismatch a build failure instead of an empty section on a live page. It is one command after any schema change:
<script setup lang="ts">
// Fetched once, at build time, into the prerendered payload.
const { data } = await useSanityContent<BlogIndexQueryResult>(
blogIndexQuery
)
// Paging and search are derived from it — no second request.
const matching = computed(() =>
(data.value?.posts ?? []).filter(matchesFilters)
)
</script>Make the registry check itself
Generated types are worth more when something is forced to agree with them. The block registry here closes with satisfies Record<RegisteredWebComponentType, ComponentData>, so a typo, a stale entry after a rename, or a block with no component fails typecheck rather than rendering nothing.
import type { HeroSimple, ComponentProps } from '~~/types'
// The generated type is the prop contract — a renamed schema
// field breaks the component, at build time, by name.
interface Props extends ComponentProps<HeroSimple> {}
const props = defineProps<Props>()Queries have types too
A projection narrows a document, and the generated result type narrows with it — so a field you forgot to project is a type error at the point of use, not a blank space on the page. The typography reference page is the same idea applied to content: one place where every thing the editor can do is visible at once.

Written by
Avery Lin
Content Architect
Avery designs content models for teams moving off page-builder CMSes, and writes about keeping structured content structured.


