---
title: "Drizzle TypeBox Integration"
description: "Drizzle TypeBox Integration automates the creation of runtime validation schemas directly from Drizzle ORM table and view definitions using the TypeBox library. By translating database columns, nul..."
last_updated: "2026-10-12T08:14:00.811777+00:00"
canonical_url: "https://www.doc0.dev/docs/e1b68fed-3c4e-4c95-b2ba-ebf050f78025/technical/ecosystem-packages/drizzle-typebox-integration"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [drizzle-typebox/src/column.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts)
- [drizzle-orm/type-tests/mysql/tables.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/type-tests/mysql/tables.ts)
- [drizzle-valibot/src/column.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-valibot/src/column.ts)
- [drizzle-arktype/src/column.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/column.ts)
- [drizzle-kit/src/introspect-pg.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/introspect-pg.ts)
- [drizzle-valibot/src/column.types.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-valibot/src/column.types.ts)
- [drizzle-orm/type-tests/singlestore/tables.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/type-tests/singlestore/tables.ts)
- [drizzle-kit/src/introspect-mysql.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/introspect-mysql.ts)
- [drizzle-kit/src/introspect-singlestore.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/introspect-singlestore.ts)
- [drizzle-zod/src/column.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-zod/src/column.ts)
- [drizzle-kit/src/serializer/gelSchema.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/serializer/gelSchema.ts)
- [drizzle-typebox/src/column.types.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.types.ts)
- [drizzle-typebox/src/schema.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts)
- [drizzle-valibot/src/schema.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-valibot/src/schema.ts)
- [drizzle-typebox/src/utils.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/utils.ts)
- [drizzle-zod/src/column.types.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-zod/src/column.types.ts)
- [drizzle-kit/src/serializer/pgSchema.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/serializer/pgSchema.ts)
- [drizzle-typebox/src/schema.types.internal.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.types.internal.ts)
- [drizzle-kit/src/serializer/mysqlSchema.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/serializer/mysqlSchema.ts)
- [drizzle-orm/src/singlestore-core/columns/text.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/singlestore-core/columns/text.ts)
- [drizzle-valibot/src/utils.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-valibot/src/utils.ts)
- [drizzle-orm/src/sqlite-core/columns/text.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sqlite-core/columns/text.ts)
- [drizzle-zod/src/utils.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-zod/src/utils.ts)
- [drizzle-valibot/src/schema.types.internal.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-valibot/src/schema.types.internal.ts)
- [drizzle-arktype/src/schema.types.internal.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.internal.ts)
- [drizzle-zod/src/schema.types.internal.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-zod/src/schema.types.internal.ts)
- [drizzle-arktype/src/column.types.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/column.types.ts)
- [drizzle-typebox/src/index.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/index.ts)
</details>

## Overview

Drizzle TypeBox Integration automates the creation of runtime validation schemas directly from Drizzle ORM table and view definitions using the TypeBox library. By translating database columns, nullability constraints, defaults, and relational structures into TypeBox schemas, it eliminates boilerplate schema duplication and maintains synchronization between database models and application validation. The package provides generators such as `createSelectSchema`, `createInsertSchema`, and `createUpdateSchema`, along with customizable schema factories that handle operation-specific column optionality and database-specific types [drizzle-typebox/src/schema.ts:88-143](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L88-L143). Static type inference resolves TypeScript types from the generated TypeBox schemas, supporting advanced column types, enums, and custom refinements [drizzle-typebox/src/column.types.ts:12-58](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.types.ts#L12-L58), [drizzle-typebox/src/schema.types.internal.ts:39-60](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.types.internal.ts#L39-L60).

## Public Package API Surface

### Top-Level Exports and Generators

The `drizzle-typebox` package exposes its primary functionality through modular entry points and re-exports from core source files [drizzle-typebox/src/index.ts:1-6](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/index.ts#L1-L6). Top-level schema generators include `createSelectSchema`, `createInsertSchema`, and `createUpdateSchema`, which construct TypeBox validation schemas from database entities such as tables, views, and PostgreSQL enums [drizzle-typebox/src/schema.ts:88-113](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L88-L113). Additionally, the factory helper `createSchemaFactory` allows developers to supply custom TypeBox instances for schema generation [drizzle-typebox/src/schema.ts:115-143](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L115-L143).

```typescript
export function createSchemaFactory(options?: CreateSchemaFactoryOptions) {
	const createSelectSchema: CreateSelectSchema = (
		entity: Table | View | PgEnum<[string, ...string[]]>,
		refine?: Record<string, any>,
	) => {
		if (isPgEnum(entity)) {
			return handleEnum(entity, options);
		}
		const columns = getColumns(entity);
		return handleColumns(columns, refine ?? {}, selectConditions, options) as any;
	};

	const createInsertSchema: CreateInsertSchema = (
		entity: Table,
		refine?: Record<string, any>,
	) => {
		const columns = getColumns(entity);
		return handleColumns(columns, refine ?? {}, insertConditions, options) as any;
	};

	const createUpdateSchema: CreateUpdateSchema = (
		entity: Table,
		refine?: Record<string, any>,
	) => {
		const columns = getColumns(entity);
		return handleColumns(columns, refine ?? {}, updateConditions, options) as any;
	};

	return { createSelectSchema, createInsertSchema, createUpdateSchema };
```
Sources: [drizzle-typebox/src/schema.ts:115-143](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L115-L143)

### Custom TypeBox Types and Helpers

The package defines specialized custom schemas and utility helpers to handle non-standard database types that do not map directly to standard TypeBox primitives [drizzle-typebox/src/column.ts:62-65](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L62-L65). This includes `literalSchema`, `jsonSchema`, `bufferSchema`, and enum mapping functions [drizzle-typebox/src/column.ts:62-69](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L62-L69). A custom type registry entry for `'Buffer'` validates binary instances at runtime [drizzle-typebox/src/column.ts:64-65](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L64-L65).

| Export Name | Origin File | Description |
| :--- | :--- | :--- |
| `createSelectSchema` | `drizzle-typebox/src/schema.ts` | Generates a select validation schema for tables, views, or enums [drizzle-typebox/src/schema.ts:88-97](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L88-L97). |
| `createInsertSchema` | `drizzle-typebox/src/schema.ts` | Generates an insert validation schema handling defaults and generated columns [drizzle-typebox/src/schema.ts:99-105](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L99-L105). |
| `createUpdateSchema` | `drizzle-typebox/src/schema.ts` | Generates an update validation schema making fields optional [drizzle-typebox/src/schema.ts:107-113](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L107-L113). |
| `createSchemaFactory` | `drizzle-typebox/src/schema.ts` | Factory function accepting custom TypeBox instance options [drizzle-typebox/src/schema.ts:115-143](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L115-L143). |
| `literalSchema` | `drizzle-typebox/src/column.ts` | Union schema matching string, number, boolean, or null values [drizzle-typebox/src/column.ts:62](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L62). |
| `jsonSchema` | `drizzle-typebox/src/column.ts` | Union schema covering literals, arrays, and string-keyed records [drizzle-typebox/src/column.ts:63](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L63). |
| `bufferSchema` | `drizzle-typebox/src/column.ts` | Custom TypeBox schema definition configured via `TypeRegistry` for `Buffer` [drizzle-typebox/src/column.ts:64-65](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L64-L65). |
| `mapEnumValues` | `drizzle-typebox/src/column.ts` | Transforms an array of string values into an object record mapping keys to values [drizzle-typebox/src/column.ts:67-69](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L67-L69). |

Sources: [drizzle-typebox/src/column.ts:62-69](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L62-L69), [drizzle-typebox/src/schema.ts:88-143](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L88-L143)

> [!NOTE]
> The `bufferSchema` registers a custom `Buffer` check against `TypeRegistry` at module initialization time, requiring consumers to import `drizzle-typebox` so that TypeBox evaluates binary buffer instances correctly during validation [drizzle-typebox/src/column.ts:64-65](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L64-L65).

Sources: [drizzle-typebox/src/column.ts:64-65](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L64-L65)

## Column Type Translation to TypeBox

### Core Translation Logic

The translation process inspects individual database columns and maps them to appropriate TypeBox validation schemas using `columnToSchema` [drizzle-typebox/src/column.ts:71-141](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L71-L141). Columns containing predefined enums are processed first, generating a TypeBox enum schema via `mapEnumValues` if enum values exist, or falling back to a standard string schema [drizzle-typebox/src/column.ts:74-76](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L74-L76).

```typescript
export function columnToSchema(column: Column, t: typeof typebox): TSchema {
	let schema!: TSchema;

	if (isWithEnum(column)) {
		schema = column.enumValues.length ? t.Enum(mapEnumValues(column.enumValues)) : t.String();
	}

```
Sources: [drizzle-typebox/src/column.ts:71-77](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L71-L77)

If the column is not an enum, the translation checks specific column types and general data types. Specialized geometric and vector types from PostgreSQL are mapped directly to tuples, objects, or arrays with dimension constraints [drizzle-typebox/src/column.ts:80-103](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L80-L103). For instance, `PgGeometry` and `PgPointTuple` columns translate to a two-element number tuple, while `PgHalfVector` and `PgVector` translate to number arrays constrained by column dimensions [drizzle-typebox/src/column.ts:80-95](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L80-L95).

```typescript
if (isColumnType<PgGeometry<any> | PgPointTuple<any>>(column, ['PgGeometry', 'PgPointTuple'])) {
	schema = t.Tuple([t.Number(), t.Number()]);
} else if (
	isColumnType<PgPointObject<any> | PgGeometryObject<any>>(column, ['PgGeometryObject', 'PgPointObject'])
) {
	schema = t.Object({ x: t.Number(), y: t.Number() });
} else if (isColumnType<PgHalfVector<any> | PgVector<any>>(column, ['PgHalfVector', 'PgVector'])) {
	schema = t.Array(
		t.Number(),
		column.dimensions
			? {
				minItems: column.dimensions,
				maxItems: column.dimensions,
			}
			: undefined,
	);
```
Sources: [drizzle-typebox/src/column.ts:80-95](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L80-L95)

### Primitive and General Data Types

When a column does not match specialized geometry or vector types, translation falls back to general `column.dataType` properties or specific numeric boundaries [drizzle-typebox/src/column.ts:115-133](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L115-L133). PostgreSQL array columns preserve base column definitions and size constraints recursively, whereas generic array types default to an array of any values [drizzle-typebox/src/column.ts:105-116](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L105-L116).

| Data Type | Target TypeBox Schema | Source Reference |
| :--- | :--- | :--- |
| `array` (PgArray) | `t.Array(columnToSchema(baseColumn), { minItems, maxItems })` | [drizzle-typebox/src/column.ts:105-114](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L105-L114) |
| `array` (Generic) | `t.Array(t.Any())` | [drizzle-typebox/src/column.ts:115-116](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L115-L116) |
| `number` | `numberColumnToSchema(column, t)` | [drizzle-typebox/src/column.ts:117-118](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L117-L118) |
| `bigint` | `bigintColumnToSchema(column, t)` | [drizzle-typebox/src/column.ts:119-120](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L119-L120) |
| `boolean` | `t.Boolean()` | [drizzle-typebox/src/column.ts:121-122](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L121-L122) |
| `date` | `t.Date()` | [drizzle-typebox/src/column.ts:123-124](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L123-L124) |
| `string` | `stringColumnToSchema(column, t)` | [drizzle-typebox/src/column.ts:125-126](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L125-L126) |
| `json` | `jsonSchema` | [drizzle-typebox/src/column.ts:127-128](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L127-L128) |
| `custom` | `t.Any()` | [drizzle-typebox/src/column.ts:129-130](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L129-L130) |
| `buffer` | `bufferSchema` | [drizzle-typebox/src/column.ts:131-132](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L131-L132) |

Sources: [drizzle-typebox/src/column.ts:105-133](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L105-L133)

> [!WARNING]
> Unrecognized column types that fail to match any explicit conditional branch default to `t.Any()` as a final fallback, bypassing strict runtime property validation for those specific fields [drizzle-typebox/src/column.ts:136-138](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L136-L138).

Sources: [drizzle-typebox/src/column.ts:136-138](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L136-L138)

## Table and View Schema Generation

### Extracting and Handling Fields

Schema generation begins by evaluating whether the input entity is a Drizzle table or view. The `getColumns` helper function inspects the entity, calling `getTableColumns` if it is a table or `getViewSelectedFields` if it is a view [drizzle-typebox/src/schema.ts:16-18](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L16-L18).

```typescript
export function getColumns(tableLike: Table | View) {
	return isTable(tableLike) ? getTableColumns(tableLike) : getViewSelectedFields(tableLike);
}
```
Sources: [drizzle-typebox/src/schema.ts:16-18](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L16-L18)

Once individual field definitions are acquired, `handleColumns` iterates over the record entries, recursively processing nested relations or resolving columns against active factory conditions [drizzle-typebox/src/schema.ts:28-60](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L28-L60). If a selected entry is an object rather than a column or SQL expression, it retrieves child columns and recursively invokes `handleColumns` [drizzle-typebox/src/schema.ts:29-33](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L29-L33).

```typescript
for (const [key, selected] of Object.entries(columns)) {
	if (!is(selected, Column) && !is(selected, SQL) && !is(selected, SQL.Aliased) && typeof selected === 'object') {
		const columns = isTable(selected) || isView(selected) ? getColumns(selected) : selected;
		columnSchemas[key] = handleColumns(columns, refinements[key] ?? {}, conditions, factory);
		continue;
	}
```
Sources: [drizzle-typebox/src/schema.ts:28-33](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L28-L33)

### Schema Conditions and Operations

Different database operations impose distinct requirements on whether fields must be optional, nullable, or omitted entirely. These rules are governed by three internal condition sets: `selectConditions`, `insertConditions`, and `updateConditions` [drizzle-typebox/src/schema.ts:70-86](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L70-L86).

| Condition Set | Never Omit Rule (`never`) | Optional Rule (`optional`) | Nullable Rule (`nullable`) | Source Reference |
| :--- | :--- | :--- | :--- | :--- |
| `selectConditions` | `() => false` | `() => false` | `(column) => !column.notNull` | [drizzle-typebox/src/schema.ts:70-74](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L70-L74) |
| `insertConditions` | Generated always columns (`always`) | Not null or has default | `(column) => !column.notNull` | [drizzle-typebox/src/schema.ts:76-80](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L76-L80) |
| `updateConditions` | Generated always columns (`always`) | `() => true` | `(column) => !column.notNull` | [drizzle-typebox/src/schema.ts:82-86](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L82-L86) |

Sources: [drizzle-typebox/src/schema.ts:70-86](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L70-L86)

> [!NOTE]
> Columns defined with `generated always as` or `generatedIdentity` of type `'always'` are strictly filtered out during insert and update schema generation via the `never` condition check [drizzle-typebox/src/schema.ts:77-83](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L77-L83).

Sources: [drizzle-typebox/src/schema.ts:77-83](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L77-L83)

### Factory Functions and Enums

The public generators `createSelectSchema`, `createInsertSchema`, and `createUpdateSchema` orchestrate these condition sets against database tables, views, or PostgreSQL enums [drizzle-typebox/src/schema.ts:88-113](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L88-L113). When evaluating a PostgreSQL enum via `createSelectSchema`, the utility delegates directly to `handleEnum`, mapping enum values using the provided or default TypeBox instance [drizzle-typebox/src/schema.ts:65-68](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L65-L68), [drizzle-typebox/src/schema.ts:92-94](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L92-L94). Custom TypeBox instances and shared options can also be bundled by invoking `createSchemaFactory`, which returns bound generator functions sharing the same configuration context [drizzle-typebox/src/schema.ts:115-144](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L115-L144).

```typescript
export function createSchemaFactory(options?: CreateSchemaFactoryOptions) {
	const createSelectSchema: CreateSelectSchema = (
		entity: Table | View | PgEnum<[string, ...string[]]>,
		refine?: Record<string, any>,
	) => {
		if (isPgEnum(entity)) {
			return handleEnum(entity, options);
		}
		const columns = getColumns(entity);
		return handleColumns(columns, refine ?? {}, selectConditions, options) as any;
	};
```
Sources: [drizzle-typebox/src/schema.ts:115-125](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.ts#L115-L125)

## Static Type Inference Mechanics

### Schema Construction and Operations

Type-level transformations handle the translation of Drizzle table definitions and column properties into valid TypeBox object schemas using `BuildSchema` [drizzle-typebox/src/schema.types.internal.ts:39-59](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.types.internal.ts#L39-L59). This utility iterates over record entries, filtering out columns where `ColumnIsGeneratedAlwaysAs` evaluates to true [drizzle-typebox/src/schema.types.internal.ts:46](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.types.internal.ts#L46). Depending on the operation mode (`select`, `insert`, or `update`), columns are wrapped or modified using helper handlers [drizzle-typebox/src/column.types.ts:85-91](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.types.ts#L85-L91).

| Operation Type | Nullability Handling (`notNull`) | Default Value Handling (`hasDefault`) | Optionality Rule | Source Reference |
| :--- | :--- | :--- | :--- | :--- |
| `select` | `!notNull` adds `t.TNull` union | None | Never optional | [drizzle-typebox/src/column.types.ts:66-70](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.types.ts#L66-L70) |
| `insert` | `!notNull` adds `t.TNull` union | `hasDefault` wraps in `t.TOptional` | Optional if nullable or has default | [drizzle-typebox/src/column.types.ts:72-77](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.types.ts#L72-L77) |
| `update` | `!notNull` adds `t.TNull` union | Always wraps in `t.TOptional` | Always optional | [drizzle-typebox/src/column.types.ts:79-83](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.types.ts#L79-L83) |

Sources: [drizzle-typebox/src/column.types.ts:66-83](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.types.ts#L66-L83)

> [!NOTE]
> During insert operations, columns marked as `notNull` without a default value remain required, whereas nullable columns and columns with defaults are wrapped in `t.TOptional` [drizzle-typebox/src/column.types.ts:72-77](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.types.ts#L72-L77).

Sources: [drizzle-typebox/src/column.types.ts:72-77](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.types.ts#L72-L77)

### Refinements and Key Validation

Refinements allow overriding or transforming generated column schemas [drizzle-typebox/src/schema.types.internal.ts:14-20](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.types.internal.ts#L14-L20). The `HandleRefinement` type checks whether a refinement function is provided, applies it to the underlying column schema, appends nullability if the column is nullable, and wraps the result in an optional modifier when processing update schemas [drizzle-typebox/src/schema.types.internal.ts:22-30](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.types.internal.ts#L22-L30).

Sources: [drizzle-typebox/src/schema.types.internal.ts:22-30](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.types.internal.ts#L22-L30)

To maintain type safety when refining schemas, `NoUnknownKeys` inspects refinement keys against comparison schemas [drizzle-typebox/src/schema.types.internal.ts:61-69](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.types.internal.ts#L61-L69). If an unknown key is detected in the refinement object, it returns a `DrizzleTypeError` [drizzle-typebox/src/schema.types.internal.ts:68](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.types.internal.ts#L68).

Sources: [drizzle-typebox/src/schema.types.internal.ts:61-69](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.types.internal.ts#L61-L69)

> [!WARNING]
> Supplying an unrecognized column name inside a refinement object triggers a static `DrizzleTypeError` via `NoUnknownKeys`, halting compilation before invalid schemas can be constructed [drizzle-typebox/src/schema.types.internal.ts:61-69](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.types.internal.ts#L61-L69).

Sources: [drizzle-typebox/src/schema.types.internal.ts:61-69](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.types.internal.ts#L61-L69)

## Custom Type Extensions and Overrides

Generated schemas can be tailored using specialized helper structures and built-in type bindings designed for binary and structured data. For complex objects, JSON helper schemas unite literal values, arrays, and record structures into a single validating union [drizzle-typebox/src/column.ts:62-63](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L62-L63). 

```typescript
export const literalSchema = t.Union([t.String(), t.Number(), t.Boolean(), t.Null()]);
export const jsonSchema: JsonSchema = t.Union([literalSchema, t.Array(t.Any()), t.Record(t.String(), t.Any())]) as any;
```
Sources: [drizzle-typebox/src/column.ts:62-63](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L62-L63)

Binary buffer handling relies on custom registry registration using TypeBox's extension API. The runtime type registry evaluates buffer columns by verifying runtime `Buffer` instances [drizzle-typebox/src/column.ts:64-65](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L64-L65).

```typescript
TypeRegistry.Set('Buffer', (_, value) => value instanceof Buffer); // eslint-disable-line no-instanceof/no-instanceof
export const bufferSchema: BufferSchema = { [Kind]: 'Buffer', type: 'buffer' } as any;
```
Sources: [drizzle-typebox/src/column.ts:64-65](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L64-L65)

> [!TIP]
> Custom buffer column translation depends on registering the custom keyword `'Buffer'` with `TypeRegistry.Set`, ensuring TypeBox can correctly serialize and validate Node.js Buffer instances [drizzle-typebox/src/column.ts:64-65](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L64-L65).

Sources: [drizzle-typebox/src/column.ts:64-65](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts#L64-L65)

## Related

- [Drizzle Zod Integration](https://www.doc0.dev/docs/e1b68fed-3c4e-4c95-b2ba-ebf050f78025/technical/ecosystem-packages/drizzle-zod-integration)
- [Table and Column Models](https://www.doc0.dev/docs/e1b68fed-3c4e-4c95-b2ba-ebf050f78025/technical/core-architecture/table-and-column-models)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/e1b68fed-3c4e-4c95-b2ba-ebf050f78025/llms.txt) for all pages in this wiki.
