Schema
Generated TypeScript types
Generate deterministic TypeScript interfaces for your collections with myna types generate.
myna types generate turns canonical collection schemas into a standalone TypeScript module: one interface per collection plus a MynaCollections registry. Generation is pure and deterministic — the same schemas always yield byte-identical output, and no user-written files are ever touched.
$ myna types generate --out src/myna-types.ts
Options
| Flag | Effect |
|---|---|
--schema-dir <dir> |
Read schemas from a specific local directory (default myna/, resolved against the linked project root). |
--deployed |
Generate from the deployed schemas (latest version per collection) instead of local files. |
--out <file> |
Write to a file; without it, the module is printed to stdout. |
By default types come from your local schema files, loaded with the same conventions as myna schema diff. Use --deployed to match exactly what the API serves, regardless of local edits.
Output shape
Collections are sorted by name. Each becomes an export interface named as the PascalCase of the collection key (blog_posts → BlogPosts), with a doc comment carrying the label and kind. Field descriptions become doc comments; optional fields (required: false) get ?. The module starts with a header comment and a JsonValue type alias, and ends with the registry:
export type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };
/** Blog posts (collection) */
export interface Posts {
title: string;
slug: string;
status?: "draft" | "review" | "live";
body: string;
publishedAt?: string;
cover?: string;
author?: string;
tags?: string[];
seo?: {
metaTitle?: string;
metaDescription?: string;
};
}
export interface MynaCollections {
"posts": {
fields: Posts;
sortable: "title" | "slug" | "status" | "publishedAt";
reference: "author";
};
}
MynaCollections is the registry the SDK consumes. Alongside the field payload it records two things the field types alone cannot express:
sortable— the fields the query engine can order and filter by (scalars, excluding localized fields). A markdownbodyand a texttitleare bothstring, but only one of them can be sorted on, so the distinction has to be carried separately.reference— the reference fieldsincludecan resolve.
Using them
Pass the registry to createMyna and the client stops returning Record<string, unknown>:
import { createMyna } from "@myna-sh/sdk";
import type { MynaCollections } from "./myna.generated";
const myna = createMyna<MynaCollections>({ project: "my-site" });
const posts = await myna.entries.list("posts", { order: "-publishedAt" });
posts.data[0].fields.title; // string — no cast
The compiler then rejects what the API would reject at runtime:
await myna.entries.list("nope"); // unknown collection
await myna.entries.list("posts", { order: "body" }); // markdown is not sortable
await myna.entries.list("posts", { filter: { body: "x" } });
await myna.entries.list("posts", { include: ["title"] }); // not a reference field
await myna.entries.list("posts", { fields: ["nope"] });
Passing no type parameter keeps the previous untyped behavior, so adopting this is opt-in and nothing breaks by ignoring it.
Type mapping
| Field type | Generated type |
|---|---|
text |
string, or a string-literal union when enum is set |
slug |
string |
markdown |
string |
number |
number |
boolean |
boolean |
date / datetime |
string (ISO date / ISO datetime with offset) |
json |
JsonValue |
asset |
string (asset id), string[] when multiple |
reference |
string (entry id), string[] when multiple |
object |
inline object type from its nested fields |
list |
T[] where T follows the same mapping for the item kind (enum text items are parenthesized unions; object items are inline object types) |
References and assets are ids, not expanded documents — resolve them through the SDK or API.
Recommended workflow
Commit the generated file. It is stable output, so diffs stay meaningful and CI can verify it is current:
$ myna schema push
$ myna types generate --out src/myna-types.ts
$ git add myna/ src/myna-types.ts && git commit -m "Add subtitle to posts"
Regenerate after every schema push; a clean git diff on the generated file after regenerating means your types match the schemas. The file header marks it as generated — do not edit it by hand.
Next
- Deploying schema changes — the diff/push flow that these types track.
- Quickstart — end-to-end setup including type generation.
