# Type Generation

> Generate TypeScript types from your ORM schema for row-aware query inference

Package: Kunii
Canonical: https://kuratchi.dev/docs/kunii/type-generation
Markdown: https://kuratchi.dev/docs/kunii/type-generation.md

## `kunii/codegen`

For full row-type inference on every `db.<table>.where(...).first()`, generate a `.d.ts` from your schema:

```ts
import { generateTypes } from '@kuratchi/kunii/codegen';
import { appSchema } from './schema';
import { writeFile } from 'node:fs/promises';

const dts = generateTypes(appSchema);
await writeFile('src/db-types.d.ts', dts);
```

The generated file exports one `XxxRow` interface per table plus an `XxxOrm` top-level interface. Use it to type your `db`:

```ts
import { kunii } from '@kuratchi/kunii';
import type { AppOrm } from './db-types';
import { appSchema } from './schema';

const db = kunii(env.DB, appSchema) as unknown as AppOrm;

const u = await db.users.where({ id: 1 }).first();
// u.data.email -> typed as string
// u.data.name  -> typed as string | null
```

## Type mapping

| Schema column | TS type |
|---|---|
| `text not null` | `string` |
| `text` | `string \| null` |
| `integer` | `number \| null` |
| `boolean` mode | `boolean \| null` |
| `timestamp_ms` mode | `number \| null` |
| `real` | `number \| null` |
| `blob` | `ArrayBuffer \| null` |
| `enum(a,b,c)` | `"a" \| "b" \| "c"` |
| `json` (default) | `any \| null` |
| primary key | always non-null |

## JSON column shapes

By default JSON columns are `any | null`. Override per-column with the `jsonShapes` option:

```ts
const dts = generateTypes(appSchema, {
  jsonShapes: {
    users: { preferences: "import('./types').UserPrefs" },
  },
});
```

The override value is the TS expression emitted verbatim, typically an imported type alias.

## Options

- `ormName` - name of the top-level interface. Defaults to `<SchemaName>Orm` PascalCased.
- `importFrom` - module specifier for the `Table` import. Defaults to `'kunii'`.
- `jsonShapes` - per-table per-column JSON shape overrides.

## Limitations

- Relations do not currently flow through the type system. `include({ posts: ... })` works at runtime, but the resulting `posts` field on each parent row is still `any`.

## Read next

- [Querying](/docs/kunii/querying)
- [JSON Columns](/docs/kunii/json-columns)
- [Schema DSL](/docs/kunii/schema-dsl)
