Relevant source files
The following files were used as context for generating this wiki page:
- drizzle-typebox/src/column.ts
- drizzle-orm/type-tests/mysql/tables.ts
- drizzle-valibot/src/column.ts
- drizzle-arktype/src/column.ts
- drizzle-kit/src/introspect-pg.ts
- drizzle-valibot/src/column.types.ts
- drizzle-orm/type-tests/singlestore/tables.ts
- drizzle-kit/src/introspect-mysql.ts
- drizzle-kit/src/introspect-singlestore.ts
- drizzle-zod/src/column.ts
- drizzle-kit/src/serializer/gelSchema.ts
- drizzle-typebox/src/column.types.ts
- drizzle-typebox/src/schema.ts
- drizzle-valibot/src/schema.ts
- drizzle-typebox/src/utils.ts
- drizzle-zod/src/column.types.ts
- drizzle-kit/src/serializer/pgSchema.ts
- drizzle-typebox/src/schema.types.internal.ts
- drizzle-kit/src/serializer/mysqlSchema.ts
- drizzle-orm/src/singlestore-core/columns/text.ts
- drizzle-valibot/src/utils.ts
- drizzle-orm/src/sqlite-core/columns/text.ts
- drizzle-zod/src/utils.ts
- drizzle-valibot/src/schema.types.internal.ts
- drizzle-arktype/src/schema.types.internal.ts
- drizzle-zod/src/schema.types.internal.ts
- drizzle-arktype/src/column.types.ts
- drizzle-typebox/src/index.ts
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. 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, drizzle-typebox/src/schema.types.internal.ts:39-60.
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. 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. Additionally, the factory helper createSchemaFactory allows developers to supply custom TypeBox instances for schema generation drizzle-typebox/src/schema.ts:115-143.
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
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. This includes literalSchema, jsonSchema, bufferSchema, and enum mapping functions drizzle-typebox/src/column.ts:62-69. A custom type registry entry for 'Buffer' validates binary instances at runtime drizzle-typebox/src/column.ts:64-65.
| 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. |
createInsertSchema | drizzle-typebox/src/schema.ts | Generates an insert validation schema handling defaults and generated columns drizzle-typebox/src/schema.ts:99-105. |
createUpdateSchema | drizzle-typebox/src/schema.ts | Generates an update validation schema making fields optional drizzle-typebox/src/schema.ts:107-113. |
createSchemaFactory | drizzle-typebox/src/schema.ts | Factory function accepting custom TypeBox instance options drizzle-typebox/src/schema.ts:115-143. |
literalSchema | drizzle-typebox/src/column.ts | Union schema matching string, number, boolean, or null values drizzle-typebox/src/column.ts:62. |
jsonSchema | drizzle-typebox/src/column.ts | Union schema covering literals, arrays, and string-keyed records drizzle-typebox/src/column.ts:63. |
bufferSchema | drizzle-typebox/src/column.ts | Custom TypeBox schema definition configured via TypeRegistry for Buffer drizzle-typebox/src/column.ts:64-65. |
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. |
Sources: drizzle-typebox/src/column.ts:62-69, drizzle-typebox/src/schema.ts:88-143
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.
Sources: drizzle-typebox/src/column.ts:64-65
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. 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.
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
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. 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.
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
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. 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.
| Data Type | Target TypeBox Schema | Source Reference |
|---|---|---|
array (PgArray) | t.Array(columnToSchema(baseColumn), { minItems, maxItems }) | drizzle-typebox/src/column.ts:105-114 |
array (Generic) | t.Array(t.Any()) | drizzle-typebox/src/column.ts:115-116 |
number | numberColumnToSchema(column, t) | drizzle-typebox/src/column.ts:117-118 |
bigint | bigintColumnToSchema(column, t) | drizzle-typebox/src/column.ts:119-120 |
boolean | t.Boolean() | drizzle-typebox/src/column.ts:121-122 |
date | t.Date() | drizzle-typebox/src/column.ts:123-124 |
string | stringColumnToSchema(column, t) | drizzle-typebox/src/column.ts:125-126 |
json | jsonSchema | drizzle-typebox/src/column.ts:127-128 |
custom | t.Any() | drizzle-typebox/src/column.ts:129-130 |
buffer | bufferSchema | drizzle-typebox/src/column.ts:131-132 |
Sources: drizzle-typebox/src/column.ts:105-133
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.
Sources: drizzle-typebox/src/column.ts:136-138
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.
export function getColumns(tableLike: Table | View) {
return isTable(tableLike) ? getTableColumns(tableLike) : getViewSelectedFields(tableLike);
}Sources: drizzle-typebox/src/schema.ts:16-18
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. 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.
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
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.
| 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 |
insertConditions | Generated always columns (always) | Not null or has default | (column) => !column.notNull | drizzle-typebox/src/schema.ts:76-80 |
updateConditions | Generated always columns (always) | () => true | (column) => !column.notNull | drizzle-typebox/src/schema.ts:82-86 |
Sources: drizzle-typebox/src/schema.ts:70-86
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.
Sources: drizzle-typebox/src/schema.ts:77-83
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. 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, drizzle-typebox/src/schema.ts:92-94. 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.
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
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. This utility iterates over record entries, filtering out columns where ColumnIsGeneratedAlwaysAs evaluates to true drizzle-typebox/src/schema.types.internal.ts:46. 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.
| 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 |
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 |
update | !notNull adds t.TNull union | Always wraps in t.TOptional | Always optional | drizzle-typebox/src/column.types.ts:79-83 |
Sources: drizzle-typebox/src/column.types.ts:66-83
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.
Sources: drizzle-typebox/src/column.types.ts:72-77
Refinements and Key Validation
Refinements allow overriding or transforming generated column schemas drizzle-typebox/src/schema.types.internal.ts:14-20. 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.
Sources: drizzle-typebox/src/schema.types.internal.ts:22-30
To maintain type safety when refining schemas, NoUnknownKeys inspects refinement keys against comparison schemas drizzle-typebox/src/schema.types.internal.ts:61-69. If an unknown key is detected in the refinement object, it returns a DrizzleTypeError drizzle-typebox/src/schema.types.internal.ts:68.
Sources: drizzle-typebox/src/schema.types.internal.ts:61-69
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.
Sources: drizzle-typebox/src/schema.types.internal.ts:61-69
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.
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
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.
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
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.
Sources: drizzle-typebox/src/column.ts:64-65
Related
On This Page
OverviewPublic Package API SurfaceTop-Level Exports and GeneratorsCustom TypeBox Types and HelpersColumn Type Translation to TypeBoxCore Translation LogicPrimitive and General Data TypesTable and View Schema GenerationExtracting and Handling FieldsSchema Conditions and OperationsFactory Functions and EnumsStatic Type Inference MechanicsSchema Construction and OperationsRefinements and Key ValidationCustom Type Extensions and OverridesRelated