# Generating TypeScript types from your schema

DatoCMS records don't have a predetermined structure, so the [JavaScript CMA client](https://www.datocms.com/docs/content-management-api/using-the-nodejs-clients.md) cannot provide strict TypeScript types out of the box: every field comes back typed as `unknown`. To get full type-safety, auto-completions, and inline type hints in your editor, the CLI exposes a `schema:generate` command that reads your project's schema and emits a TypeScript definition file describing every model and block.

## The command

After [installing and linking the CLI](https://www.datocms.com/docs/cli.md), generate the schema with:

Terminal window

```bash
npx datocms schema:generate schema.ts
```

The output is a TypeScript module you commit to your repo and import wherever you call the CMA client.

## What gets generated

For each model and block in your project, the command emits an `ItemTypeDefinition` **type** (used as a generic in CMA calls) and a runtime **constant** (used to reference the model's ID or build relationships):

```typescript
// schema.ts: generated by `npx datocms schema:generate`.
//
// Do not hand-edit. Re-run the generator whenever the schema changes.

import type { ItemTypeDefinition } from '@datocms/cma-client';

type EnvironmentSettings = { locales: 'en' | 'it' };

export type Article = ItemTypeDefinition<
  EnvironmentSettings,
  '76hhD-LaS5CM3NPJw0991w',
  {
    name: { type: 'string' };
    slug: { type: 'slug' };
    accent_color: { type: 'color' };
    sections: { type: 'rich_text'; blocks: ArticleSection };
  }
>;

export const Article = {
  ID: '76hhD-LaS5CM3NPJw0991w',
  REF: { type: 'item_type', id: '76hhD-LaS5CM3NPJw0991w' },
} as const;
```

The generated file then turns calls like `client.items.find<Schema.Article>(id)` into fully typed expressions. For the full set of patterns (using markers in API calls, extracting concrete field types, narrowing block unions, typing whole payloads), see [Type-safe development with TypeScript](https://www.datocms.com/docs/content-management-api/resources/item.md#type-safe-development-with-typescript) in the CMA section.

## Two ways to generate the schema

The CLI lets you generate types in two complementary ways, depending on how you plan to use them.

###### Standalone: for your application code

The most common case: a single `schema.ts` file in your repo that your application code imports.

Terminal window

```bash
npx datocms schema:generate ./src/datocms-schema.ts
```

You typically commit this file and re-run the command whenever the project schema changes.

###### Inline: within a migration script

A migration script represents the schema at a **specific point in its history**: its job is to take the project from state *N* to state *N+1*. The standalone `schema.ts` file, on the other hand, always reflects the **latest** state of the project. If a migration written six months ago referenced `Schema.Article` from the global file, and `Article` has since been renamed or restructured, the migration would silently start type-checking against a schema it was never written for.

To keep a migration type-safe against its own historical view of the project, the CLI can **inline** the relevant model definitions directly into the migration file at scaffold time:

Terminal window

```bash
npx datocms migrations:new 'tweak articles' --schema=Article,Author
```

Use `--schema=all` to inline every model. The migration ends up self-contained: it carries its own snapshot of the schema, decoupled from the global `schema.ts`, and continues to type-check correctly even after the project schema evolves.

## Targeting a specific subset

Two flags narrow what gets generated:

-   `--item-types=product,article`: generate only the listed models. Useful when your project has hundreds of models and you only need a few in your app.
-   `--environment=my-sandbox`: generate from a specific sandbox environment instead of primary. Useful when previewing a schema change before promotion.
    

## Keeping types in sync

The generated file is only as fresh as the last `schema:generate` run. If your project schema changes (a new model, a renamed field) and you forget to regenerate, your TypeScript types will silently drift from the actual API shape.

A common pattern is to **automate the regeneration**: a nightly CI job (or a webhook triggered on schema changes) runs `npx datocms schema:generate` and opens a pull request whenever the output differs from the version in `git`. That way the types in your repo are always one merge away from being correct, and any drift is visible at code review time.

## Related content in "DatoCMS CLI"

- [CLI Overview](https://www.datocms.com/docs/cli.md)
- [Environment, migration and maintenance commands](https://www.datocms.com/docs/cli/environment-migration-and-maintenance-commands.md)
- [Generating TypeScript types from your schema](https://www.datocms.com/docs/cli/generating-typescript-schema.md)
- [Importing content from other CMSs](https://www.datocms.com/docs/cli/importing-from-other-cms.md)
- [CLI for AI coding agents](https://www.datocms.com/docs/cli/cli-commands-for-ai-coding-agents.md)
- [Authenticate with an API token](https://www.datocms.com/docs/cli/authenticate-with-api-token.md)
- [Profiles and multi-project setup](https://www.datocms.com/docs/cli/profiles-and-multi-project-setup.md)