Mismatch between TypeGen-generated types and actual data: TypeGen generates `_type` field for non-array object fields, but Sanity Content Lake doesn't store it
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Stale
- Tech stack
- typescript
- Domain
- tooling
Research direction
Reproduce the mismatch with the add-table schema by running sanity schema extract and sanity typegen generate, then compare the generated Table type with the GROQ result. Trace how non-array named object fields and array members are represented, and add coverage showing that the generated type matches the stored data without incorrectly requiring _type.
Written by the indexing model from the issue text.
Description
Describe the bug
TypeGen generates types that include _type for named object types used as non-array fields, but Sanity's Content Lake does not store the _type field for these objects when there's only one possible type. This causes a mismatch between the generated TypeScript types and the actual query results.
To Reproduce
-
Install the
@sanity/tableplugin which defines a named object typetable -
Create a schema that uses
tableas a direct object field (not in an array):// add-table.ts import { defineField, defineType } from 'sanity' export default defineType({ name: 'addTable', title: 'Table', type: 'object', fields: [ defineField({ name: 'title', title: 'Title', type: 'string', }), defineField({ name: 'table', title: 'Table', type: 'table', // references the named type from @sanity/table }), ], }) -
Run
sanity schema extractandsanity typegen generate -
Query the data using GROQ and observe the actual result vs generated types
Expected behavior
The generated type should match the actual stored data. Since Sanity doesn't store _type for non-array object fields with a single possible type, the generated type should not include it.
Actual behavior
TypeGen generates:
export type Table = {
_type: 'table' // ← Generated, but NOT in actual data
rows?: Array<
{
_key: string
} & TableRow
>
}
But the actual GROQ query result is:
{
"_type": "addTable",
"table": {
"rows": [
{
"_key": "d5794e3b-e44d-42b8-b0de-cbdb6032b9df",
"_type": "tableRow",
"cells": ["Column 1", "Column 2", "Column 3"]
}
]
}
}
Note that:
addTablehas_type: "addTable"✓tabledoes NOT have_type: "table"✗ (mismatch with generated type)tableRow(in array) has_type: "tableRow"✓
Analysis
The extracted schema correctly includes _type for the table type:
{
"name": "table",
"type": "type",
"value": {
"type": "object",
"attributes": {
"_type": {
"type": "objectAttribute",
"value": {
"type": "string",
"value": "table"
}
},
"rows": { ... }
}
}
}
However, Sanity's Content Lake optimizes storage by not storing _type for non-array object fields when there's only one possible type (since it can be inferred from the schema). TypeGen should account for this behavior.
Workaround
Use TypeScript utility types to remove _type from the affected types:
import type { Except } from 'type-fest'
import type { Table } from 'types/sanity.types'
type ActualTable = Except<Table, '_type'>
Which versions of Sanity are you using?
`@sanity/client`: ^7.8.2
`@sanity/table`: ^1.1.3
`sanity`: ^4.10.2
Which versions of Node.js / npm are you running?
npm: 10.9.2
Node: v22.16.0
What operating system are you using?
Linux (Ubuntu 22.04.5 LTS) running inside WSL 2 (v2.4.13.0) within Windows (Windows 11 Pro, version 24H2, OS build 26100.7623)
Additional context
Might be related to sanity-io/codegen#20 which also involves TypeGen generating incorrect _type values that don't match actual query results.
The distinction seems to be:
- Array members →
_typeIS stored (needed for type discrimination when multiple types are possible) - Non-array object fields with single type →
_typeis NOT stored (optimization, can be inferred)
TypeGen should understand this storage behavior and generate types accordingly, perhaps by marking _type as optional for non-array object fields, or omitting it entirely when only one type is possible.
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 2
- Avg merge
- 3d 11h
- Merged PRs (30d)
- 5
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from sanity-io/codegen
-
Difficulty 3/5 1-2 days Newbie friendliness 74/100
-
Difficulty 5/5 Over a week Newbie friendliness 42/100
-
Difficulty 3/5 1-2 days Newbie friendliness 48/100
-
Difficulty 4/5 3-5 days Newbie friendliness 45/100
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
All issues in sanity-io/codegen
Similar issues
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster no-stale P3
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 76/100
-
code-quality refactoring
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
github/gh-aw-firewall#8816 ·
-
integration:quickjs org:external priority:backlog topic:code-interpreter topic:middleware type:feature
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
langchain-ai/deepagents#6450 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
vercel/react-tweet#225 ·