Validation Guide
Every generated Atscript type has a .validator() method for runtime validation.
In normal application code, you usually use it for:
- validating request or form input
- narrowing
unknowndata to a real TypeScript type - stripping or rejecting unexpected properties
- handling partial updates safely
import { Product } from './product.as'
const validator = Product.validator()1. Validate One Value
Safe Mode
Safe mode returns false on failure and acts as a type guard:
if (validator.validate(data, true)) {
// TypeScript now knows data is Product
console.log(data.name, data.price)
} else {
console.log(validator.errors)
}This is the most practical mode for request handlers and form submissions.
Throwing Mode
Throwing mode raises ValidatorError on failure:
try {
validator.validate(data)
// data passed validation
} catch (error) {
console.error(error.message)
console.error(error.errors)
}2. Narrow unknown Data
The validator doubles as a type guard, so it works well at the edge of your app:
import { Product } from './product.as'
function handleRequest(body: unknown) {
if (Product.validator().validate(body, true)) {
// body is Product here
saveProduct(body)
}
}No manual generic parameters are needed. Atscript already knows the data shape from the model.
3. Control Unexpected Properties
Use unknownProps when inputs may contain extra fields:
const validator = Product.validator({
unknownProps: 'strip',
})Options:
'error'— fail validation if an extra field is present'ignore'— leave extra fields alone'strip'— remove extra fields from the value
'strip' is often useful for request payloads.
4. Validate Partial Updates
Use partial when validating patch-like payloads:
const patchValidator = Product.validator({
partial: true,
})Options:
false— all required properties must be presenttrue— allow missing properties at the top level'deep'— allow missing properties at every level
'deep' is useful for nested patch payloads.
5. Put Rules On The Model
Validation rules come from your .as file:
export interface User {
@expect.minLength 3
username: string
email: string.email
@expect.min 18
age: number.int
}That means one model definition can give you:
- static typing
- runtime validation
- metadata for other tools
6. Write Better Error Messages
Most validation annotations accept a custom message as the last argument:
export interface SignupForm {
@meta.required "Please enter your name"
@expect.minLength 3, "Username must be at least 3 characters"
username: string
}When validation fails, the custom message is used instead of the default one.
7. Know The Common Built-Ins
The most common validation rules come from:
- semantic types like
string.email,string.required,number.int.positive @expect.minLength@expect.maxLength@expect.min@expect.max@expect.pattern
For array uniqueness and other less common rules, see the Validation Reference.
DOs and DON'Ts
- DO expect extra fields to fail validation by default.
unknownPropsdefaults to'error'— if a payload may carry extra fields, choose'strip'or'ignore'deliberately. - DON'T forget that
'strip'mutates your input. It deletes the extra fields from the object you passed in — clone the payload first if you still need the original. - DO create the validator once and reuse it in hot paths.
.validator()builds a fresh instance on every call. Reuse is safe: eachvalidate()call resetsvalidator.errorsbefore running. - DO raise
errorLimitwhen a form needs every message. Validation stops collecting after 10 errors by default, so long forms may show an incomplete error list.
When To Read The Reference
Use the reference page when you need:
- every validator option in one place
- the exact
validate()signature ValidatorError- array uniqueness rules
- plugin hooks and external context
- manual
Validatorconstruction from runtime types
Next Steps
- Validation Reference — options, plugins, and lower-level API details
- Annotations Guide — keep validation rules on the model
- Type Definitions — understand the runtime type system behind the validator