Documentation / zerotal / validator / FormRequest
Abstract Class: FormRequest
Defined in: packages/validator/src/FormRequest.ts:65
Base class for encapsulating validation rules and optional authorization in a reusable, testable class rather than inline in each handler.
Define rules via an instance rules(r) method. Because it is an instance
method, you have full access to this.context inside your schema — enabling
patterns like unique-except-current-user validation:
rules(r: RuleBuilder) {
return {
email: r.string().email().unique('users', 'email', this.context.user?.id),
name: r.string().min(2),
};
}
Type inference: validate() uses ReturnType<T['rules']> to extract the
narrow return type of the concrete subclass's rules() method. TypeScript
evaluates this against the actual instantiated T at the call site — NOT
the base class constraint — so the returned data is fully typed.
IMPORTANT: Do NOT add an explicit return type to your rules() override.
Annotating it as Record<string, FieldRule> would widen the inferred type
and cause validate() to return Record<string, unknown> instead.
Example
// app/requests/StorePostRequest.ts
export class StorePostRequest extends FormRequest {
authorize() { return !!this.context.user; }
rules(r: RuleBuilder) {
return {
title: r.string().min(3).max(255),
body: r.string().min(10),
};
}
}
// In a file-based route or controller:
const data = await StorePostRequest.validate();
// data.title → string (fully typed — no casts needed)
Constructors
Constructor
new FormRequest():
FormRequest
Returns
FormRequest
Accessors
context
Get Signature
get
protectedcontext():HttpContext
Defined in: packages/validator/src/FormRequest.ts:75
Access the current request's HttpContext from within instance methods. Pulled from AsyncLocalStorage — no constructor injection needed.
Example
authorize() {
return !!this.context.user;
}
Returns
Methods
authorize()
authorize():
boolean|Promise<boolean>
Defined in: packages/validator/src/FormRequest.ts:89
Authorize the request before validation.
Return true to allow (default), false to deny with 403.
Access the current request via this.context.
Returns
boolean | Promise<boolean>
Example
authorize(): boolean {
return !!this.context.user;
}
rules()
rules(
_r):Record<string,FieldRule>
Defined in: packages/validator/src/FormRequest.ts:110
Define the validation rules for this request.
Override in subclasses WITHOUT an explicit return type so TypeScript infers
the narrow schema shape and validate() produces a fully-typed result.
You have full access to this.context inside this method — use it for
rules that depend on the current user, route params, or session state.
Parameters
_r
Returns
Record<string, FieldRule>
Example
rules(r: RuleBuilder) {
return {
email: r.string().email().unique('users', 'email', this.context.user?.id),
name: r.string().min(2).max(100),
};
}
macro()
staticmacro(name,fn):void
Defined in: packages/validator/src/FormRequest.ts:128
Attach a helper method to all FormRequest instances at runtime.
Designed for framework packages (e.g. @zerotal/auth) that expose
convenience methods like this.user() or this.auth().
Pair with a declaration merge on the exported FormRequest interface for
TypeScript autocomplete on the added method.
Parameters
name
string
fn
(this, ...args) => unknown
Returns
void
Example
// In @zerotal/auth's provider:
FormRequest.macro('user', function(this: FormRequest) {
return this.context.user;
});
validate()
staticvalidate<T>(this):Promise<Infer<ExtractDefs<ReturnType<T["rules"]>>>>
Defined in: packages/validator/src/FormRequest.ts:149
Validate the HTTP request against this class's rules.
The return type is fully inferred from the concrete rules() override —
no manual type assertions needed in the caller. TypeScript resolves
ReturnType<T['rules']> against the actual T at the call site, not the
base class constraint. HttpContext is pulled from per-request
AsyncLocalStorage automatically (zero arguments).
On success: returns the validated, typed data object. On failure: throws ValidationRedirectError (Inertia / web form) or ValidationJsonError (JSON API), and stores errors in the session.
Type Parameters
T
T extends FormRequest
Parameters
this
() => T
Returns
Promise<Infer<ExtractDefs<ReturnType<T["rules"]>>>>
Example
const data = await StorePostRequest.validate();
data.title // string — not unknown