# 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.
```bash
$ myna types generate --out src/myna-types.ts
```
## Options
| Flag | Effect |
|---|---|
| `--schema-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 ` | Write to a file; without it, the module is printed to stdout. |
By default types come from your local [schema files](/schema/defining-schemas), 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 `description`s 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:
```ts
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 markdown `body` and a text `title` are both `string`, but only one of them can be sorted on, so the distinction has to be carried separately.
- **`reference`** — the reference fields `include` can resolve.
## Using them
Pass the registry to `createMyna` and the client stops returning `Record`:
```ts
import { createMyna } from "@myna-sh/sdk";
import type { MynaCollections } from "./myna.generated";
const myna = createMyna({ 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:
```ts
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:
```bash
$ 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](/schema/deploying); 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](/schema/deploying) — the diff/push flow that these types track.
- [Quickstart](/getting-started/quickstart) — end-to-end setup including type generation.