Schema: Lift anonymous object types
A common pattern is to embed an object inside your document, which groups related fields together. For instance, a person might have an address made up of several fields, such as a street name and a zip code.
You can declare that object inline, without giving it a name of its own:
import {defineType, defineField} from 'sanity'
export const person = defineType({
name: 'person',
type: 'object',
fields: [
defineField({name: 'name', type: 'string'}),
defineField({
// An anonymous inline object: it has no top-level schema type of its own
name: 'address',
type: 'object',
fields: [
defineField({name: 'street', type: 'string', title: 'Street name'}),
defineField({name: 'zip', type: 'string', title: 'Zip code'}),
],
}),
],
})Sanity Studio accepts this schema, but sanity graphql deploy does not. GraphQL cannot represent an object type that has no name, so the deploy stops with a message like Encountered anonymous inline object "address" for field/type "person". To use this field with GraphQL you will need to create a top-level schema type for it. For more on the schema constraints GraphQL adds, see GraphQL.
An anonymous object inside an array raises the same error, reported by its position in the array rather than by a field name.
Lifting the object into a top-level schema type is required before you can deploy a GraphQL API, and it usually improves the data model regardless.
Defining a type globally often leads to a more thought-out and future-proof data model, since you rethink its fields in a global context — "how can I define this type so it can be reused for both businesses and person records?"
A named type is also easier to consume from an application. Sanity TypeGen can generate TypeScript types from your schema, so you don't have to mirror it by hand.
To lift a type, create a new type for it in the same way you would a person type, then import it into your schema:
import {defineType, defineField} from 'sanity'
export const address = defineType({
name: 'address',
type: 'object',
fields: [
defineField({name: 'street', type: 'string', title: 'Street name'}),
defineField({name: 'zip', type: 'string', title: 'Zip code'}),
],
})Then, in your person type, set address as the type for the address field:
import {defineType, defineField} from 'sanity'
export const person = defineType({
name: 'person',
type: 'object',
fields: [
defineField({name: 'name', type: 'string'}),
defineField({name: 'address', type: 'address'}),
],
})Register both types in your studio's schema:
import {defineConfig} from 'sanity'
import {address} from './schemaTypes/address'
import {person} from './schemaTypes/person'
export default defineConfig({
projectId: 'YOUR_PROJECT_ID',
dataset: 'production',
schema: {
types: [person, address],
},
})