Show navigationHide navigation
Generated Types
The CMS auto-generates TypeScript types from cms/octocms.config.ts into cms/__generated__/. These provide concrete, readable interfaces with fully resolved reference fields — no unknown, no deeply nested conditional types.
Quick start#
bashnpm run types:gen # Regenerate from cms/octocms.config.ts npm run types:check # Regenerate + fail if output differs (CI)
What is generated#
| File | Contents |
|---|---|
cms/__generated__/types.ts | <Collection>Fields and <Collection>Entry interfaces, EntryMap, AnyEntry |
cms/__generated__/enums.ts | CollectionName const object, COLLECTION_NAMES array, select option const objects, FieldFormat |
cms/__generated__/content.d.ts | Raw on-disk types (Raw<Collection>Fields / Raw<Collection>Entry) — before query() processing |
cms/__generated__/index.ts | Barrel re-export of types and enums |
Usage with query()#
The query() API in octocms/query.ts uses the generated EntryMap for return types. Reference fields are resolved to concrete entry types:
typescriptimport { query } from 'octocms/query'; const posts = await query('post').toArray(); // ^? PostEntry[] posts[0].fields.title; // ^? string // Blog references resolve to PostEntry[], not unknown const blog = await query('blog').first(); blog?.fields.posts; // ^? PostEntry[] // Author → Role references are fully resolved const authors = await query('author').toArray(); authors[0].fields.roles; // ^? RoleEntry[]
Usage client-side (fetch)#
The generated types can be imported in any client or server component:
typescriptimport type { PostEntry } from 'cms/__generated__'; const res = await fetch('/api/posts'); const posts: PostEntry[] = await res.json(); // Full autocomplete on posts[0].fields.title, etc.
Select option enums#
Select fields generate const objects for type-safe comparisons:
typescriptimport { ItemCategoryOption } from 'cms/__generated__'; // Const object — use as values if (item.fields.category === ItemCategoryOption.Featured) { ... } // Type — use in signatures function filterByCategory(cat: ItemCategoryOption) { ... }
Naming convention: {PascalCollection}{PascalField}Option.
Collection name enum#
typescriptimport { CollectionName, COLLECTION_NAMES } from 'cms/__generated__'; // Const object — type-safe collection name access query(CollectionName.Post).toArray(); // Array — iterate over all collection names for (const name of COLLECTION_NAMES) { ... }
Raw content types (content.d.ts)#
For validating content JSON files locally (without the admin UI), import from content.d.ts:
typescriptimport type { RawPostEntry } from 'cms/__generated__/content.d';
Key differences from resolved types:
- Image fields:
string(UUID) instead ofResolvedImageField - Reference fields:
string(key or JSON-stringified array) instead of resolved entry types - Markdown fields: Omitted (stored in companion
.mdfiles, not in JSON)
How it works#
The generator reads cms/octocms.config.ts at build time and emits TypeScript interfaces. It:
- Validates the config (same rules as
docs:genplus reference/conditional/identifier checks) - Maps each field format to its TypeScript type
- Resolves reference fields to concrete
<Collection>Entrytypes (handles cycles via TypeScript forward references) - Emits const objects for collection names and select options
Keeping types in sync#
npm run types:genregenerates the outputnpm run types:check(part ofnpm run checks) fails if the committed output differs from a fresh generation- Regeneration runs automatically as part of CI checks
Do not edit files in cms/__generated__/ by hand — they will be overwritten.