Skip to content

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 unknown data to a real TypeScript type
  • stripping or rejecting unexpected properties
  • handling partial updates safely
typescript
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:

typescript
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:

typescript
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:

typescript
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:

typescript
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:

typescript
const patchValidator = Product.validator({
  partial: true,
})

Options:

  • false — all required properties must be present
  • true — 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:

atscript
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:

atscript
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. unknownProps defaults 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: each validate() call resets validator.errors before running.
  • DO raise errorLimit when 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 Validator construction from runtime types

Next Steps

Released under the MIT License.