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
| Annotation | Applies to | Description |
|---|---|---|
@minLength(n) | string | Minimum character count |
@maxLength(n) | string | Maximum character count |
@min(n) | numeric | Minimum value |
@max(n) | numeric | Maximum value |
@regex("pat") | string | Must match regex |
@email | string | Valid email format |
@url | string | Valid URL format |
@trim | string | Strip whitespace before validation |
Recommended Usage
- 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
jsonwhen the shape varies by kind.
Related guide: Build Your First App