---
title: "Drizzle ArkType Integration"
description: "Drizzle ArkType Integration bridges Drizzle ORM definitions with the ArkType validation library by automatically generating runtime type validators and static TypeScript types from database schemas..."
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-arktype-integration"
---

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

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

- [drizzle-arktype/src/column.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/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-arktype/src/schema.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.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/serializer/gelSchema.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/serializer/gelSchema.ts)
- [drizzle-kit/src/introspect-mysql.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/introspect-mysql.ts)
- [drizzle-arktype/src/schema.types.internal.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.internal.ts)
- [drizzle-kit/src/introspect-pg.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/introspect-pg.ts)
- [drizzle-kit/src/serializer/pgSchema.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/serializer/pgSchema.ts)
- [drizzle-arktype/src/index.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/index.ts)
- [drizzle-kit/src/introspect-singlestore.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/introspect-singlestore.ts)
- [drizzle-kit/src/introspect-gel.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/introspect-gel.ts)
- [drizzle-arktype/src/column.types.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/column.types.ts)
- [drizzle-kit/src/serializer/mysqlSchema.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/serializer/mysqlSchema.ts)
- [drizzle-valibot/src/column.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-valibot/src/column.ts)
- [drizzle-kit/src/serializer/pgSerializer.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/serializer/pgSerializer.ts)
- [drizzle-arktype/src/utils.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/utils.ts)
- [drizzle-valibot/src/column.types.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-valibot/src/column.types.ts)
- [drizzle-valibot/src/schema.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-valibot/src/schema.ts)
- [drizzle-typebox/src/column.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/column.ts)
- [drizzle-kit/src/schemaValidator.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/schemaValidator.ts)
- [drizzle-kit/src/serializer/sqliteSchema.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/serializer/sqliteSchema.ts)
- [drizzle-arktype/src/schema.types.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.ts)
- [drizzle-seed/src/types/drizzleStudio.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-seed/src/types/drizzleStudio.ts)
- [drizzle-kit/src/serializer/studio.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/serializer/studio.ts)
- [integration-tests/drizzle2/pg/meta/0000_snapshot.json](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/integration-tests/drizzle2/pg/meta/0000_snapshot.json)
- [drizzle-kit/src/serializer/singlestoreSchema.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-kit/src/serializer/singlestoreSchema.ts)
- [drizzle-seed/src/types/tables.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-seed/src/types/tables.ts)
- [drizzle-typebox/src/schema.types.internal.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-typebox/src/schema.types.internal.ts)
</details>

## Overview

Drizzle ArkType Integration bridges Drizzle ORM definitions with the ArkType validation library by automatically generating runtime type validators and static TypeScript types from database schemas. Operating across tables, views, and enums, it translates column primitives, constraints, and relational selections into validated ArkType structures, powering type-safe data validation and insertions.

Sources: [drizzle-arktype/src/column.ts:66-126](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/column.ts#L66-L126), [drizzle-arktype/src/schema.ts:61-98](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.ts#L61-L98), [drizzle-arktype/src/schema.types.ts:6-48](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.ts#L6-L48)

## Public Schema Generation API

### Schema Factory Functions

The public API provides three main factory functions — `createSelectSchema`, `createInsertSchema`, and `createUpdateSchema` — to generate ArkType validation schemas from Drizzle table, view, and enum definitions. Each factory inspects the entity columns or fields, applies custom field refinements, and enforces nullability and optionality rules according to the operation type.

```typescript
export const createSelectSchema = ((
	entity: Table | View | PgEnum<[string, ...string[]]>,
	refine?: Record<string, any>,
) => {
	if (isPgEnum(entity)) {
		return type.enumerated(...entity.enumValues);
	}
	const columns = getColumns(entity);
	return handleColumns(columns, refine ?? {}, {
		never: () => false,
		optional: () => false,
		nullable: (column) => !column.notNull,
	}) as any;
}) as CreateSelectSchema;

export const createInsertSchema = ((
	entity: Table,
	refine?: Record<string, any>,
) => {
	const columns = getColumns(entity);
	return handleColumns(columns, refine ?? {}, {
		never: (column) => column?.generated?.type === 'always' || column?.generatedIdentity?.type === 'always',
		optional: (column) => !column.notNull || (column.notNull && column.hasDefault),
		nullable: (column) => !column.notNull,
	}) as any;
}) as CreateInsertSchema;

export const createUpdateSchema = ((
	entity: Table,
	refine?: Record<string, any>,
) => {
	const columns = getColumns(entity);
	return handleColumns(columns, refine ?? {}, {
		never: (column) => column?.generated?.type === 'always' || column?.generatedIdentity?.type === 'always',
		optional: () => true,
		nullable: (column) => !column.notNull,
	}) as any;
}) as CreateUpdateSchema;
```
Sources: [drizzle-arktype/src/schema.ts:61-98](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.ts#L61-L98)

The behavior of each factory function depends on specific condition evaluators configured during column iteration:

| Function | Target Entity | `never` Condition | `optional` Condition | `nullable` Condition |
| :--- | :--- | :--- | :--- | :--- |
| `createSelectSchema` | Table, View, PgEnum | Always `false` | Always `false` | `!column.notNull` |
| `createInsertSchema` | Table | `generated === 'always'` or `generatedIdentity === 'always'` | `!column.notNull || (column.notNull && column.hasDefault)` | `!column.notNull` |
| `createUpdateSchema` | Table | `generated === 'always'` or `generatedIdentity === 'always'` | Always `true` | `!column.notNull` |

```typescript
export const createSelectSchema = ((
	entity: Table | View | PgEnum<[string, ...string[]]>,
	refine?: Record<string, any>,
) => {
	if (isPgEnum(entity)) {
		return type.enumerated(...entity.enumValues);
	}
	const columns = getColumns(entity);
	return handleColumns(columns, refine ?? {}, {
		never: () => false,
		optional: () => false,
		nullable: (column) => !column.notNull,
	}) as any;
}) as CreateSelectSchema;

export const createInsertSchema = ((
	entity: Table,
	refine?: Record<string, any>,
) => {
	const columns = getColumns(entity);
	return handleColumns(columns, refine ?? {}, {
		never: (column) => column?.generated?.type === 'always' || column?.generatedIdentity?.type === 'always',
		optional: (column) => !column.notNull || (column.notNull && column.hasDefault),
		nullable: (column) => !column.notNull,
	}) as any;
}) as CreateInsertSchema;

export const createUpdateSchema = ((
	entity: Table,
	refine?: Record<string, any>,
) => {
	const columns = getColumns(entity);
	return handleColumns(columns, refine ?? {}, {
		never: (column) => column?.generated?.type === 'always' || column?.generatedIdentity?.type === 'always',
		optional: () => true,
		nullable: (column) => !column.notNull,
	}) as any;
}) as CreateUpdateSchema;
```
Sources: [drizzle-arktype/src/schema.ts:61-98](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.ts#L61-L98)

> [!NOTE]
> When `createSelectSchema` receives a `PgEnum`, it bypasses column iteration entirely and immediately constructs an ArkType enumerated validator using the enum's `enumValues`.

Sources: [drizzle-arktype/src/schema.ts:65-67](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.ts#L65-L67)

### Overloads and Refinement Signatures

The TypeScript interfaces for `createSelectSchema`, `createInsertSchema`, and `createUpdateSchema` support overloaded signatures for tables and views, as well as optional refinement objects to customize field validators.

```typescript
export interface CreateSelectSchema {
	<TTable extends Table>(table: TTable): BuildSchema<'select', TTable['_']['columns'], undefined>;
	<
		TTable extends Table,
		TRefine extends BuildRefine<TTable['_']['columns']>,
	>(
		table: TTable,
		refine?: NoUnknownKeys<TRefine, TTable['$inferSelect']>,
	): BuildSchema<'select', TTable['_']['columns'], TRefine>;

	<TView extends View>(view: TView): BuildSchema<'select', TView['_']['selectedFields'], undefined>;
	<
		TView extends View,
		TRefine extends BuildRefine<TView['_']['selectedFields']>,
	>(
		view: TView,
		refine: NoUnknownKeys<TRefine, TView['$inferSelect']>,
	): BuildSchema<'select', TView['_']['selectedFields'], TRefine>;

	<TEnum extends PgEnum<any>>(enum_: TEnum): Type<TEnum['enumValues'][number]>;
}

export interface CreateInsertSchema {
	<TTable extends Table>(table: TTable): BuildSchema<'insert', TTable['_']['columns'], undefined>;
	<
		TTable extends Table,
		TRefine extends BuildRefine<Pick<TTable['_']['columns'], keyof TTable['$inferInsert']>>,
	>(
		table: TTable,
		refine?: NoUnknownKeys<TRefine, TTable['$inferInsert']>,
	): BuildSchema<'insert', TTable['_']['columns'], TRefine>;
}

export interface CreateUpdateSchema {
	<TTable extends Table>(table: TTable): BuildSchema<'update', TTable['_']['columns'], undefined>;
	<
		TTable extends Table,
		TRefine extends BuildRefine<Pick<TTable['_']['columns'], keyof TTable['$inferInsert']>>,
	>(
		table: TTable,
		refine?: TRefine,
	): BuildSchema<'update', TTable['_']['columns'], TRefine>;
}
```
Sources: [drizzle-arktype/src/schema.types.ts:6-48](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.ts#L6-L48)

> [!IMPORTANT]
> For insert and update schemas, refinement typings are constrained via `NoUnknownKeys` to keys present in `$inferInsert`, preventing developers from specifying refinements for uninsertable or generated columns.

Sources: [drizzle-arktype/src/schema.types.ts:28-48](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.ts#L28-L48)

## Column to ArkType Conversion Pipeline

### Column Data Type Routing

The `columnToSchema` function inspects incoming Drizzle column definitions and routes them to specific ArkType validators. If a column has associated enumeration values, it generates an enumerated validator using `column.enumValues`, or falls back to `type.string` if the enumeration is empty.

```typescript
export function columnToSchema(column: Column): Type {
	let schema!: Type;

	if (isWithEnum(column)) {
		schema = column.enumValues.length ? type.enumerated(...column.enumValues) : type.string;
	}

```
Sources: [drizzle-arktype/src/column.ts:66-72](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/column.ts#L66-L72)

For specialized geometric, vector, and line types, columns map directly to fixed-tuple structures or object shapes with coordinate properties. Array columns recursively resolve their base column schema via `columnToSchema` and enforce exact element dimensions when a column size or dimension is specified.

| Column Type Matcher | Column Subtypes Checked | Generated ArkType Structure |
| :--- | :--- | :--- |
| Tuple Geometry / Point | `PgGeometry`, `PgPointTuple` | `type([type.number, type.number])` |
| Object Geometry / Point | `PgGeometryObject`, `PgPointObject` | `type({ x: type.number, y: type.number })` |
| Vector | `PgHalfVector`, `PgVector` | `type.number.array()` (with optional `.exactlyLength(column.dimensions)`) |
| Line Tuple | `PgLine` | `type([type.number, type.number, type.number])` |
| Line ABC Object | `PgLineABC` | `type({ a: type.number, b: type.number, c: type.number })` |
| Array | `PgArray` | `columnToSchema(column.baseColumn).array()` (with optional `.exactlyLength(column.size)`) |

```typescript
// Handle specific types
if (isColumnType<PgGeometry<any> | PgPointTuple<any>>(column, ['PgGeometry', 'PgPointTuple'])) {
	schema = type([type.number, type.number]);
} else if (
	isColumnType<PgPointObject<any> | PgGeometryObject<any>>(column, ['PgGeometryObject', 'PgPointObject'])
) {
	schema = type({
		x: type.number,
		y: type.number,
	});
} else if (isColumnType<PgHalfVector<any> | PgVector<any>>(column, ['PgHalfVector', 'PgVector'])) {
	schema = column.dimensions
		? type.number.array().exactlyLength(column.dimensions)
		: type.number.array();
} else if (isColumnType<PgLineTuple<any>>(column, ['PgLine'])) {
	schema = type([type.number, type.number, type.number]);
} else if (isColumnType<PgLineABC<any>>(column, ['PgLineABC'])) {
	schema = type({
		a: type.number,
		b: type.number,
		c: type.number,
	});
} // Handle other types
else if (isColumnType<PgArray<any, any>>(column, ['PgArray'])) {
	const arraySchema = columnToSchema(column.baseColumn).array();
	schema = column.size ? arraySchema.exactlyLength(column.size) : arraySchema;
} else if (column.dataType === 'array') {
	schema = type.unknown.array();
```
Sources: [drizzle-arktype/src/column.ts:74-101](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/column.ts#L74-L101)

### Primitive and Complex Type Mappings

Standard data types are resolved by checking `column.dataType`. Numeric and bigint columns delegate to dedicated boundary-resolution functions, while booleans map to `type.boolean`, dates map to `type.Date`, JSON columns map to `jsonSchema`, buffers map to `bufferSchema`, and custom types fall back to `type.unknown`.

```typescript
} else if (column.dataType === 'number') {
	schema = numberColumnToSchema(column);
} else if (column.dataType === 'bigint') {
	schema = bigintColumnToSchema(column);
} else if (column.dataType === 'boolean') {
	schema = type.boolean;
} else if (column.dataType === 'date') {
	schema = type.Date;
} else if (column.dataType === 'string') {
	schema = stringColumnToSchema(column);
} else if (column.dataType === 'json') {
	schema = jsonSchema;
} else if (column.dataType === 'custom') {
	schema = type.unknown;
} else if (column.dataType === 'buffer') {
	schema = bufferSchema;
}
```
Sources: [drizzle-arktype/src/column.ts:102-118](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/column.ts#L102-L118)

> [!NOTE]
> If a column matches none of the recognized database types or enumerations, `columnToSchema` defaults to `type.unknown` as a safe fallback validator.

Sources: [drizzle-arktype/src/column.ts:121-125](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/column.ts#L121-L125)

### Column Nullability and Operational Handling

The `HandleColumn` type utility determines whether a generated schema requires nullability or optionality wrappers based on whether an operation targets select, insert, or update statements. Nullable columns wrap their underlying schemas with `ArktypeNullable`, allowing `null` values, whereas defaultable insert columns and all update columns incorporate `ArktypeOptional`.

```typescript
export type HandleColumn<
	TType extends 'select' | 'insert' | 'update',
	TColumn extends Column,
> = TType extends 'select' ? HandleSelectColumn<GetArktypeType<TColumn>, TColumn>
	: TType extends 'insert' ? HandleInsertColumn<GetArktypeType<TColumn>, TColumn>
	: TType extends 'update' ? HandleUpdateColumn<GetArktypeType<TColumn>, TColumn>
	: GetArktypeType<TColumn>;
```
Sources: [drizzle-arktype/src/column.types.ts:35-41](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/column.types.ts#L35-L41)

> [!IMPORTANT]
> JSON columns use specialized type extraction via `GetArktypeType`, which resolves unconstrained JSON data columns to the `Json` union type rather than standard `unknown` descriptors.

Sources: [drizzle-arktype/src/column.types.ts:9-14](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/column.types.ts#L9-L14)

## Table and View Column Resolution

### Column Extraction and Recursive Traversal

The `getColumns` helper inspects whether an incoming entity is a table or view, invoking `getTableColumns` or `getViewSelectedFields` respectively to extract its base field mappings.

```typescript
function getColumns(tableLike: Table | View) {
	return isTable(tableLike) ? getTableColumns(tableLike) : getViewSelectedFields(tableLike);
}
```
Sources: [drizzle-arktype/src/schema.ts:10-12](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.ts#L10-L12)

The `handleColumns` engine iterates over column records and recursively processes nested object relations or inline selections whenever an entry is an object and not an instance of `Column`, `SQL`, or `SQL.Aliased`.

```typescript
function handleColumns(
	columns: Record<string, any>,
	refinements: Record<string, any>,
	conditions: Conditions,
): Type {
	const columnSchemas: Record<string, Type> = {};

	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);
			continue;
		}
```
Sources: [drizzle-arktype/src/schema.ts:14-26](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.ts#L14-L26)

### Conditional Constraints and Refinement Processing

During column iteration, `handleColumns` applies operational conditions and field-level user refinements to build the final composite `Type` schema object.

```typescript

		const refinement = refinements[key];
		if (
			refinement !== undefined
			&& (typeof refinement !== 'function' || (typeof refinement === 'function' && refinement.expression !== undefined))
		) {
			columnSchemas[key] = refinement;
			continue;
		}

		const column = is(selected, Column) ? selected : undefined;
		const schema = column ? columnToSchema(column) : type.unknown;
		const refined = typeof refinement === 'function' ? refinement(schema) : schema;

		if (conditions.never(column)) {
			continue;
		} else {
			columnSchemas[key] = refined;
		}

		if (column) {
			if (conditions.nullable(column)) {
				columnSchemas[key] = columnSchemas[key]!.or(type.null);
			}

			if (conditions.optional(column)) {
				columnSchemas[key] = columnSchemas[key]!.optional() as any;
			}
		}
	}

	return type(columnSchemas);
}
```
Sources: [drizzle-arktype/src/schema.ts:27-59](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.ts#L27-L59)

> [!NOTE]
> When `conditions.never(column)` evaluates to true—such as for database-generated columns in insert or update schemas—the property is omitted from the resulting ArkType definition entirely.

Sources: [drizzle-arktype/src/schema.ts:41-45](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.ts#L41-L45)

> [!IMPORTANT]
> The `createSelectSchema`, `createInsertSchema`, and `createUpdateSchema` factories supply distinct condition rulesets governing nullability (`!column.notNull`), optionality (`!column.notNull || (column.notNull && column.hasDefault)` for inserts, always true for updates), and exclusion (`generated.type === 'always'`).

Sources: [drizzle-arktype/src/schema.ts:61-98](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.ts#L61-L98)

## Static Type Inference and Refinements

### Compile-Time Schema Inference and Utilities

Internal type utilities orchestrate compile-time schema composition, parameter validation, and refinement mapping across select, insert, and update operations. The `BuildSchema` type maps table columns or view fields into an instantiated ArkType object schema, omitting any columns marked as generated always via `ColumnIsGeneratedAlwaysAs`.

```typescript
export type BuildSchema<
	TType extends 'select' | 'insert' | 'update',
	TColumns extends Record<string, any>,
	TRefinements extends Record<string, any> | undefined,
> = type.instantiate<
	Simplify<
		{
			readonly [K in keyof TColumns as ColumnIsGeneratedAlwaysAs<TColumns[K]> extends true ? never : K]:
				TColumns[K] extends infer TColumn extends Column
					? IsRefinementDefined<TRefinements, K> extends true
						? HandleRefinement<TType, TRefinements[K & keyof TRefinements], TColumn>
					: HandleColumn<TType, TColumn>
					: TColumns[K] extends infer TNested extends SelectedFieldsFlat<Column> | Table | View ? BuildSchema<
							TType,
							GetSelection<TNested>,
							TRefinements extends object ? TRefinements[K & keyof TRefinements] : undefined
						>
					: any;
		}
	>
>;
```
Sources: [drizzle-arktype/src/schema.types.internal.ts:43-63](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.internal.ts#L43-L63)

The `Conditions` interface specifies functional predicates that determine whether columns are excluded, optional, or nullable during schema generation.

```typescript
export interface Conditions {
	never: (column?: Column) => boolean;
	optional: (column: Column) => boolean;
	nullable: (column: Column) => boolean;
}
```
Sources: [drizzle-arktype/src/schema.types.internal.ts:6-10](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.internal.ts#L6-L10)

| Condition Utility | Parameter Type | Return Type | Purpose |
| :--- | :--- | :--- | :--- |
| `never` | `column?: Column` | `boolean` | Determines if a column should be omitted entirely from the generated schema |
| `optional` | `column: Column` | `boolean` | Evaluates whether a column accepts optional input values |
| `nullable` | `column: Column` | `boolean` | Evaluates whether a column permits null values |

Sources: [drizzle-arktype/src/schema.types.internal.ts:6-10](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.internal.ts#L6-L10)

### Field Refinement and Validation Typings

User-supplied field refinements are typed and validated through dedicated utility types that ensure type safety and prevent unknown keys. `BuildRefine` constructs a mapped type over table columns, accepting either a generic ArkType schema, a refinement function returning a generic schema, or nested selections.

```typescript
export type BuildRefine<
	TColumns extends Record<string, any>,
> = {
	[K in keyof TColumns as TColumns[K] extends Column | SelectedFieldsFlat<Column> | Table | View ? K : never]?:
		TColumns[K] extends Column ? BuildRefineField<GetArktypeType<TColumns[K]>>
			: BuildRefine<GetSelection<TColumns[K]>>;
};
```
Sources: [drizzle-arktype/src/schema.types.internal.ts:16-22](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.internal.ts#L16-L22)

The `NoUnknownKeys` utility validates refinement keys against comparison schemas, returning a `DrizzleTypeError` when an unrecognized key is encountered.

```typescript
export type NoUnknownKeys<
	TRefinement extends Record<string, any>,
	TCompare extends Record<string, any>,
> = {
	[K in keyof TRefinement]: K extends keyof TCompare
		? TRefinement[K] extends Record<string, GenericSchema> ? NoUnknownKeys<TRefinement[K], TCompare[K]>
		: TRefinement[K]
		: DrizzleTypeError<`Found unknown key in refinement: "${K & string}"`>;
};
```
Sources: [drizzle-arktype/src/schema.types.internal.ts:65-73](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.internal.ts#L65-L73)

> [!CAUTION]
> Supplying an unrecognized key within a refinement object triggers `NoUnknownKeys` to evaluate a `DrizzleTypeError` string literal type, failing compilation.

Sources: [drizzle-arktype/src/schema.types.internal.ts:65-73](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.internal.ts#L65-L73)

### Refinement Resolution and Operation Handling

The `HandleRefinement` type processes user-defined refinement functions or static schemas based on the operation context (`select`, `insert`, or `update`). If a refinement is defined as a function, `HandleRefinement` checks column nullability and applies `ArktypeNullable` when not strictly not-null, and wraps the resulting schema in `ArktypeOptional` for update operations.

```typescript
type HandleRefinement<
	TType extends 'select' | 'insert' | 'update',
	TRefinement,
	TColumn extends Column,
> = TRefinement extends (schema: any) => GenericSchema ? (
		TColumn['_']['notNull'] extends true ? ReturnType<TRefinement>
			: ArktypeNullable<ReturnType<TRefinement>>
	) extends infer TSchema ? TType extends 'update' ? ArktypeOptional<TSchema>
		: TSchema
	: Type<any>
	: TRefinement;
```
Sources: [drizzle-arktype/src/schema.types.internal.ts:24-34](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.internal.ts#L24-L34)

The presence of a refinement for any given key is verified by `IsRefinementDefined`, which inspects whether the refinement property extends `GenericSchema` or a valid refinement builder function.

```typescript
type IsRefinementDefined<
	TRefinements extends Record<string | symbol | number, any> | undefined,
	TKey extends string | symbol | number,
> = TRefinements extends object ? TRefinements[TKey] extends GenericSchema | ((schema: any) => any) ? true
	: false
	: false;
```
Sources: [drizzle-arktype/src/schema.types.internal.ts:36-41](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.internal.ts#L36-L41)

> [!NOTE]
> During schema building, `IsRefinementDefined` acts as a conditional gate: when it evaluates to true, `HandleRefinement` processes the custom rule; otherwise, standard column rules via `HandleColumn` take effect.

Sources: [drizzle-arktype/src/schema.types.internal.ts:51-54](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/schema.types.internal.ts#L51-L54)

## Specialized Column Schemas and Helpers

### Standalone Column Builders and Primitives

The library exports standalone schema definitions and helper utilities designed for validating specific runtime structures, primitive types, and buffer values without requiring a full table configuration. The `literalSchema` accepts strings, numbers, booleans, and null values, serving as the foundation for broader structural definitions.

```typescript
export const literalSchema = type.string.or(type.number).or(type.boolean).or(type.null);
export const jsonSchema = literalSchema.or(type.unknown.as<any>().array()).or(type.object.as<Record<string, any>>());
export const bufferSchema = type.unknown.narrow((value) => value instanceof Buffer).as<Buffer>().describe( // eslint-disable-line no-instanceof/no-instanceof
	'a Buffer instance',
);
```
Sources: [drizzle-arktype/src/column.ts:60-64](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/column.ts#L60-L64)

The `jsonSchema` composes `literalSchema` with unknown arrays and arbitrary object records to validate nested JSON payloads. Meanwhile, `bufferSchema` uses a narrowing check to enforce runtime validation for `Buffer` instances with a descriptive error string.

```typescript
export const jsonSchema = literalSchema.or(type.unknown.as<any>().array()).or(type.object.as<Record<string, any>>());
export const bufferSchema = type.unknown.narrow((value) => value instanceof Buffer).as<Buffer>().describe( // eslint-disable-line no-instanceof/no-instanceof
	'a Buffer instance',
);
```
Sources: [drizzle-arktype/src/column.ts:61-64](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/column.ts#L61-L64)

| Helper Schema | Underlying Definition | Target Runtime Structure |
| :--- | :--- | :--- |
| `literalSchema` | `type.string.or(type.number).or(type.boolean).or(type.null)` | Primitive scalars and null values |
| `jsonSchema` | `literalSchema.or(type.unknown.array()).or(type.object)` | Nested JSON-compatible data structures |
| `bufferSchema` | `type.unknown.narrow((value) => value instanceof Buffer)` | Node.js `Buffer` byte arrays |

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

### Enum Constraint Checking and Resolution

Column definitions containing restricted sets of allowed values are processed using `isWithEnum` to determine whether an explicit enumeration constraint exists. When enum values are present and non-empty, `columnToSchema` constructs an ArkType enumerated type using `type.enumerated(...column.enumValues)`. If the column lacks explicit values or the array is empty, it falls back to a standard string type.

```typescript
if (isWithEnum(column)) {
	schema = column.enumValues.length ? type.enumerated(...column.enumValues) : type.string;
}
```
Sources: [drizzle-arktype/src/column.ts:69-71](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/column.ts#L69-L71)

The utility function `isWithEnum` verifies column configurations by checking whether the `enumValues` property exists on the column object, is an array, and contains a positive length. The related `isPgEnum` helper casts this check to validate PostgreSQL-specific enum entities.

```typescript
export function isWithEnum(column: Column): column is typeof column & { enumValues: [string, ...string[]] } {
	return 'enumValues' in column && Array.isArray(column.enumValues) && column.enumValues.length > 0;
}

export const isPgEnum: (entity: any) => entity is PgEnum<[string, ...string[]]> = isWithEnum as any;
```
Sources: [drizzle-arktype/src/utils.ts:10-14](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/utils.ts#L10-L14)

> [!CAUTION]
> Passing a column object with an empty `enumValues` array will bypass the enumerated schema builder and default to an unrestricted string validator.

Sources: [drizzle-arktype/src/column.ts:69-71](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-arktype/src/column.ts#L69-L71)

## 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.
