Type System
How Zanith provides compile-time type safety from schema definition to query results — without generating any code. This page covers every type export and utility.
The inference chain
Types flow automatically through the entire pipeline. Each step preserves and refines the type information from the previous step.
carries scalar type
extracts type map
maps to ModelAPI<T>
returns T[]
Scalar type mapping
Each builder method carries its TypeScript type as a phantom generic parameter:
| Builder method | TypeScript type | With .nullable() |
|---|---|---|
m.string() / m.text() / m.uuid() | string | string | null |
m.int() / m.float() / m.decimal() | number | number | null |
m.boolean() | boolean | boolean | null |
m.datetime() | Date | Date | null |
m.bigint() | bigint | bigint | null |
m.json() | unknown | unknown | null |
m.json | T | T | null |
m.bytes() | Buffer | Buffer | null |
m.enum(E) | string | string | null |
Type exports
Import these types from 'zanith' for advanced type-level operations:
import type { // Model & field inference InferModelFields, // Extract field type map from a TypedModelDefinition InferFieldTypes, // Extract type map from a Record<string, FieldBuilder> InferFieldType, // Extract T from a single FieldBuilder<T> TypedModelDefinition, // Model definition with phantom field types // Query input types TypedWhereInput, // Where clause constrained to model field names & types FilterOpsFor, // Map a scalar type to its filter operators // Client types TypedZanithClient, // Fully typed client (model names → ModelAPI instances) // Utility types Nullify, // Make all fields T | null (for LEFT JOIN propagation)} from 'zanith';InferModelFields
Extracts the field type map from a model definition. Use this when you need to reference a model's types in your own code.
const User = defineModel((m) => ({ name: 'User', table: 'users', fields: { email: m.string(), name: m.string().nullable(), age: m.int(), },})); type UserFields = InferModelFields<typeof User>;// UserFields = { email: string, name: string | null, age: number }TypedWhereInput
A mapped type that constrains the whereclause to valid field names and appropriate filter operators for each field's type.
type UserWhere = TypedWhereInput<UserFields>; // Valid:const where1: UserWhere = { email: '[email protected]' };const where2: UserWhere = { age: { gt: 18, lt: 65 } };const where3: UserWhere = { OR: [{ role: 'ADMIN' }, { role: 'USER' }] }; // TypeScript errors:const bad1: UserWhere = { emale: 'test' }; // ❌ unknown fieldconst bad2: UserWhere = { age: { gt: 'old' } }; // ❌ string, not numberFilterOpsFor
Maps a scalar TypeScript type to its available filter operators:
| Scalar type | Filter type | Available operators |
|---|---|---|
string | StringFilterOps | equals, not, in, notIn, contains, startsWith, endsWith, lt, gt |
number | NumberFilterOps | equals, not, in, notIn, lt, lte, gt, gte |
boolean | BooleanFilterOps | equals, not |
Date | DateFilterOps | equals, not, lt, lte, gt, gte |
Nullify
Wraps every field in T | null. Used internally for LEFT JOIN nullable propagation — fields from LEFT JOINed models may be null even if the field itself isn't nullable.
type UserFields = { email: string, name: string | null, age: number };type NullableUser = Nullify<UserFields>;// NullableUser = { email: string | null, name: string | null, age: number | null }TypedZanithClient
The fully typed client type. Maps model names to ModelAPI<T> instances with correct field types.
type Models = { User: typeof User, Post: typeof Post };type Client = TypedZanithClient<Models>; // Client.user → ModelAPI<{ email: string, name: string | null, ... }>// Client.post → ModelAPI<{ title: string, content: string | null, ... }>