Kizaki
ReferenceInspire

Validation Types

Declare validated input schemas for exposed functions and API payloads using @validation types.

@validation types define validated shapes for @expose function parameters and API payloads. They produce no database table. The runtime enforces field constraints on every call — invalid inputs are rejected before your function body runs.

Struct

@validation type CreateNoteInput {
  title:    string @minLength(1) @maxLength(255) @trim,
  content:  string @minLength(1) @maxLength(10000),
  priority: int    @min(1) @max(5) = 3,
  email:    string @email,
  website:  string? @url,
}

Fields are required by default. Append ? for optional. Add = value for a default.

Partial

All fields become optional. Use for update inputs where callers send only the fields they want to change.

@validation type UpdateNoteInput = Partial<CreateNoteInput>

Omitted fields stay omitted — source defaults are not re-applied on omission.

Pick

Select a subset of fields from an existing type.

@validation type NoteTitleOnly = Pick<CreateNoteInput, [title]>

Omit

Exclude specific fields from an existing type.

@validation type PublicNoteInput = Omit<CreateNoteInput, [email]>

Intersection

Extend a type with additional fields.

@validation type CreateNoteWithSource = CreateNoteInput & {
  source:   string,
  referrer: string?,
}

Discriminated Unions

Define inputs that take different shapes depending on a discriminant field.

@validation type PaymentMethod =
  | { type: "card",  cardNumber: string }
  | { type: "bank",  routingNumber: string, accountNumber: string }

The runtime uses the type field to select the matching variant for validation.

Using In Server Functions

Declare the validation type as a TypeScript parameter type. The generated @kizaki/client stubs carry the same types.

import { CreateNoteInput, UpdateNoteInput } from "@kizaki/schema";

/** @expose */
export async function createNote(input: CreateNoteInput) {
  const me = getPrincipal();
  const [note] = await query(
    insert(Note).values({ ...input, ownerId: me.id }).returning(),
  );
  return note;
}

/** @expose */
export async function updateNote(id: string, input: UpdateNoteInput) {
  const [note] = await query(
    update(Note)
      .set(input)
      .where(eq(Note.id, id))
      .returning(),
  );
  return note;
}

Available Validation Annotations

AnnotationApplies toDescription
@minLength(n)stringMinimum character count
@maxLength(n)stringMaximum character count
@min(n)numericMinimum value
@max(n)numericMaximum value
@regex("pat")stringMust match regex
@emailstringValid email format
@urlstringValid URL format
@trimstringStrip whitespace before validation
  • Use Partial<T> for every update input — do not re-declare fields as optional by hand.
  • Keep validation types small and purpose-shaped. One type per exposed function is common.
  • Prefer discriminated unions over untyped json when the shape varies by kind.

Related guide: Build Your First App

On this page