> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dottxt.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeBox

[TypeBox](https://github.com/sinclairzx81/typebox) is a TypeScript library where types **are** JSON Schema objects. No export step is needed; the schema you write is the schema you send.

## Install

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
npm install @sinclair/typebox ai @ai-sdk/openai
```

## Basic usage

TypeBox types produce JSON Schema directly. Pass them to the Vercel AI SDK's `jsonSchema()` wrapper to use with dottxt:

<CodeGroup>
  ```typescript TypeBox theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  import { Type, Static } from "@sinclair/typebox";
  import { createOpenAI } from "@ai-sdk/openai";
  import { generateObject, jsonSchema } from "ai";

  const Contact = Type.Object({
    name: Type.String(),
    email: Type.String(),
    role: Type.String(),
  }, { additionalProperties: false });

  type Contact = Static<typeof Contact>;

  const dottxt = createOpenAI({
    baseURL: "https://api.dottxt.ai/v1",
    apiKey: process.env.DOTTXT_API_KEY!,
  });

  const { object } = await generateObject({
    model: dottxt.chat("openai/gpt-oss-20b"),
    schema: jsonSchema<Contact>(Contact),
    schemaName: "contact",
    prompt: "Extract: John Smith <john@acme.com>, VP Engineering",
  });

  console.log(object.name);
  ```

  ```json JSON Schema theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  {
    "type": "object",
    "properties": {
      "name": { "type": "string" },
      "email": { "type": "string" },
      "role": { "type": "string" }
    },
    "required": ["name", "email", "role"],
    "additionalProperties": false
  }
  ```
</CodeGroup>

## Adding constraints

TypeBox methods map directly to JSON Schema keywords:

<CodeGroup>
  ```typescript TypeBox theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  const UserProfile = Type.Object({
    username: Type.String({ minLength: 3, maxLength: 20, pattern: "^[a-z0-9_]+$" }),
    bio: Type.String({ maxLength: 200 }),
    role: Type.Union([
      Type.Literal("admin"),
      Type.Literal("editor"),
      Type.Literal("viewer"),
    ]),
  }, { additionalProperties: false });
  ```

  ```json JSON Schema theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  {
    "type": "object",
    "properties": {
      "username": {
        "type": "string",
        "minLength": 3,
        "maxLength": 20,
        "pattern": "^[a-z0-9_]+$"
      },
      "bio": {
        "type": "string",
        "maxLength": 200
      },
      "role": {
        "anyOf": [
          { "const": "admin", "type": "string" },
          { "const": "editor", "type": "string" },
          { "const": "viewer", "type": "string" }
        ]
      }
    },
    "required": ["username", "bio", "role"],
    "additionalProperties": false
  }
  ```
</CodeGroup>

## Optional and nullable fields

```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
const Lead = Type.Object({
  name: Type.String(),
  email: Type.String(),
  company: Type.Optional(Type.Union([Type.String(), Type.Null()])),
  phone: Type.Optional(Type.Union([Type.String(), Type.Null()])),
}, { additionalProperties: false });
```

`Type.Optional()` removes the field from `required`. `Type.Union([Type.String(), Type.Null()])` allows `null`.

## Arrays

```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
const Survey = Type.Object({
  question: Type.String(),
  options: Type.Array(Type.String(), { minItems: 2, maxItems: 6 }),
  tags: Type.Array(Type.String(), { maxItems: 5 }),
}, { additionalProperties: false });
```

## Nested objects

```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
const Address = Type.Object({
  street: Type.String(),
  city: Type.String(),
  country: Type.String(),
}, { additionalProperties: false });

const Customer = Type.Object({
  name: Type.String(),
  billing_address: Address,
  shipping_address: Address,
}, { additionalProperties: false });
```

## Type mapping

| TypeBox              | JSON Schema                     | TypeScript       |
| -------------------- | ------------------------------- | ---------------- |
| `Type.String()`      | `{"type": "string"}`            | `string`         |
| `Type.Number()`      | `{"type": "number"}`            | `number`         |
| `Type.Integer()`     | `{"type": "integer"}`           | `number`         |
| `Type.Boolean()`     | `{"type": "boolean"}`           | `boolean`        |
| `Type.Null()`        | `{"type": "null"}`              | `null`           |
| `Type.Array(T)`      | `{"type": "array", "items": T}` | `T[]`            |
| `Type.Literal("x")`  | `{"const": "x"}`                | `"x"`            |
| `Type.Union([A, B])` | `{"anyOf": [A, B]}`             | `A \| B`         |
| `Type.Optional(T)`   | removes from `required`         | `T \| undefined` |
| `Type.Object({...})` | `{"type": "object", ...}`       | `{...}`          |

## Notes

* Pass `{ additionalProperties: false }` as the second argument to `Type.Object()` when you want strict object schemas. TypeBox does not set this by default, so omit it only when you intentionally want an open object.
* TypeBox types are plain objects, so `JSON.stringify(Contact)` gives you the JSON Schema directly.
* `Static<typeof Schema>` extracts the TypeScript type from a TypeBox schema, giving you type safety on both ends.

## Next steps

* [Zod authoring](/json-schema/authoring/zod)
* [Pydantic authoring](/json-schema/authoring/pydantic)
* [Integrations overview](/integrations/overview)
* [JSON Schema overview](/json-schema/overview)
