
Security News
The Changelog Podcast: Practical Steps to Stay Safe on npm
Learn the essential steps every developer should take to stay secure on npm and reduce exposure to supply chain attacks.
@decaf-ts/decorator-validation
Advanced tools
A TypeScript decorator-driven validation and model framework. It lets you:
Documentation available here
Decorator Validation is a TypeScript library that centers on two complementary pillars:
Core runtime architecture
Intent of the library
Design principles
This guide shows concrete, TypeScript-accurate examples for the main public APIs exported by the library. Examples are inspired by patterns used across the repo tests and typical usage of decorator-driven validation and models.
Notes
Description: Marks a class as a model. The constructor is wrapped to bind model utilities and run a global builder (if any).
import { model, Model, ModelArg } from "@decaf-ts/decorator-validation";
@model()
class User extends Model {
@prop()
id!: string;
@prop()
name!: string;
constructor(arg?: ModelArg<User>) {
super(arg);
}
}
const u = new User();
Extending from the Model class is optional but highly recommended. Regardless, if decorated with @model(), the constructor signature must be compatible.
When using a class for validation, eg hasErrors() only, @model() is not required.
When a class is decorated with @model(), the framework invokes a model building function right after the instance is constructed. This builder initializes your model from the argument you pass to the constructor.
There are two builder strategies:
Your model constructors should accept an optional argument and pass it to super so the builder can use it.
You can change between builder functions by using:
import { required, Model, model, ModelArg } from "@decaf-ts/decorator-validation";
@model()
class Child extends Model {
@required()
name!: string;
constructor(arg?: ModelArg<Child>) {
super(arg);
}
}
@model()
class Parent extends Model {
@required()
name!: string;
@required()
child!: Child;
constructor(arg?: ModelArg<Parent>) {
super(arg);
}
}
// Default builder is Model.fromModel
let parent = new Parent({
child: {
name: "child"
}
})
parent.child instanceof Child; // true
Model.setBuilder(Model.fromObject);
parent = new Parent({
child: {
name: "child"
}
})
parent.child instanceof Child; // false
Description: Declares which hashing strategy to use when hashing model instances.
import { model, hashedBy, ModelArg, prop } from "@decaf-ts/decorator-validation";
@model()
@hashedBy("sha256", "utf8")
class FileInfo extends Model {
@prop()
path!: string;
@prop()
size!: number;
constructor(arg?: ModelArg<FileInfo>) {
super(arg)
}
}
Description: Declares which serializer to use for (de)serializing model instances.
import { prop, ModelArg, model, serializedBy } from "@decaf-ts/decorator-validation";
@model()
@serializedBy("json")
class Settings extends Model {
@prop()
theme!: string;
@prop()
locale!: string;
constructor(arg?: ModelArg<Settings>){
super(arg)
}
}
Description: Applies textual documentation metadata to a class, property, or method.
import { model, description, Model } from "@decaf-ts/decorator-validation";
@model()
@description("Represents an application user")
class User extends Model {
@description("Unique identifier")
id!: string;
// ...
}
Each decorator writes metadata for a corresponding Validator. Use them on model fields.
Description: Registers a property with the model system. This is required for model construction so the property participates in metadata, serialization, hashing, validation discovery, etc.
Important
Description: Field must be present and non-empty.
import { Model, required, model } from "@decaf-ts/decorator-validation";
@model()
class User extends Model {
@required()
username!: string;
//...
}
Description: Numeric or date boundaries.
import { model } from "@decaf-ts/decorator-validation";
import { min } from "@decaf-ts/decorator-validation";
import { max } from "@decaf-ts/decorator-validation";
@model()
class Product extends Model {
@min(0)
@max(1000)
price!: number;
}
Description: String length boundaries.
import { model, Model } from "@decaf-ts/decorator-validation";
import { minLength, maxLength } from "@decaf-ts/decorator-validation";
@model()
class Credentials extends Model {
@minLength(8)
@maxLength(64)
password!: string;
}
Description: String must match a pattern.
import { model } from "@decaf-ts/decorator-validation";
import { pattern, model } from "@decaf-ts/decorator-validation";
@model()
class Vehicle extends Model {
@pattern(/^[A-Z]{2}-\d{2}-[A-Z]{2}$/)
plate!: string;
}
Description: Must be a valid email.
import { model } from "@decaf-ts/decorator-validation";
import { email } from "@decaf-ts/decorator-validation";
@model()
class Contact extends Model {
@email()
email!: string;
}
Description: Must be a valid URL.
import { model } from "@decaf-ts/decorator-validation";
import { url } from "@decaf-ts/decorator-validation";
@model()
class Link extends Model {
@url()
href!: string;
}
Description: Enforces a runtime type match (e.g., Number, String, Date).
import { model } from "@decaf-ts/decorator-validation";
import { type } from "@decaf-ts/decorator-validation";
@model()
class Measurement extends Model {
@type(Number)
value!: number;
}
Description: Value must equal the provided value or another property.
import { model } from "@decaf-ts/decorator-validation";
import { equals } from "@decaf-ts/decorator-validation";
@model()
class Confirmation extends Model {
password!: string;
@equals(":password")
confirm!: string;
}
Description: Numeric or date comparisons.
import { model } from "@decaf-ts/decorator-validation";
import { greaterThan, greaterThanOrEqual, lessThan, lessThanOrEqual } from "@decaf-ts/decorator-validation";
@model()
class Range extends Model {
@greaterThan(0)
@lessThanOrEqual(100)
ratio!: number;
}
Description: Numeric step constraints.
import { model, Model } from "@decaf-ts/decorator-validation";
import { step } from "@decaf-ts/decorator-validation";
@model()
class Slider extends Model {
@step(0.5)
value!: number;
}
Description: Constrains value to be one of the provided list.
import { model, Model } from "@decaf-ts/decorator-validation";
import { list } from "@decaf-ts/decorator-validation";
@model()
class ThemeSettingm extends Model {
@list(["light", "dark", "system"])
theme!: "light" | "dark" | "system";
}
Description: Must be different from another property.
import { model, Model } from "@decaf-ts/decorator-validation";
import { diff } from "@decaf-ts/decorator-validation";
@model()
class Credentials extends Model {
username!: string;
@diff(":username")
password!: string;
}
Description: Date constraints for a date-typed field.
import { model, Model } from "@decaf-ts/decorator-validation";
import { date } from "@decaf-ts/decorator-validation";
@model()
class Booking extends Model {
@date({ min: new Date("2025-01-01"), max: new Date("2025-12-31") })
start!: Date;
}
Description: Password strength constraints (e.g., min length, uppercase, digits, symbols) depending on validator configuration.
import { model } from "@decaf-ts/decorator-validation";
import { password, Model } from "@decaf-ts/decorator-validation";
@model()
class Account extends Model{
@password({ minLength: 10 })
password!: string;
}
Description: Marks a model as involving async validation rules (decorator flag helper).
import { model } from "@decaf-ts/decorator-validation";
import { async } from "@decaf-ts/decorator-validation";
@model()
@async()
class Signup {
// fields that may use async validators
}
Use the model validation utilities to evaluate rules defined by decorators.
import { model, required, email, validate, Model } from "@decaf-ts/decorator-validation";
@model()
class Contact extends Model {
@required()
@email()
email!: string;
constructor(arg?: ModelArg<Contact>) {
super(arg);
}
}
const c = new Contact({
email: "not-an-email"
});
let errs = c.hasErrors(); // resolves to a list of errors or undefined
@async()
@model()
class User extends Model {
@required()
@email()
email!: string;
constructor(arg?: ModelArg<User>) {
super(arg);
}
}
const u = new User({
email: "not-an-email"
})
errs = await u.hasErrors(); // resolves to a list of errors or undefined
Description: Swap the active validator registry and optionally migrate validators.
import { Validation, ValidatorRegistry } from "@decaf-ts/decorator-validation";
const custom = new ValidatorRegistry();
Validation.setRegistry(custom, v => v); // trivial migration
Description: Register one or more Validator implementations or definitions.
import { Validation, Validator, validator } from "@decaf-ts/decorator-validation";
@validator("ALWAYS_OK")
class AlwaysOk extends Validator {
hasErrors(...args: any[]) { return []; }
}
Validation.register(new AlwaysOk());
Description: Retrieve a registered validator by key.
import { Validation, ValidationKeys } from "@decaf-ts/decorator-validation";
const requiredValidator = Validation.get(ValidationKeys.REQUIRED);
Description: Build a reflect-metadata key or list all registered keys.
import { Validation } from "@decaf-ts/decorator-validation";
const metaKey = Validation.key("REQUIRED");
const allKeys = Validation.keys();
If you have bug reports, questions or suggestions please create a new issue.
I am grateful for any contributions made to this project. Please read this to get started.
The first and easiest way you can support it is by Contributing. Even just finding a typo in the documentation is important.
Financial support is always welcome and helps keep both me and the project alive and healthy.
So if you can, if this project in any way. either by learning something or simply by helping you save precious time, please consider donating.
This project is released under the MIT License.
By developers, for developers...
FAQs
simple decorator based validation engine
The npm package @decaf-ts/decorator-validation receives a total of 1,264 weekly downloads. As such, @decaf-ts/decorator-validation popularity was classified as popular.
We found that @decaf-ts/decorator-validation demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 5 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Learn the essential steps every developer should take to stay secure on npm and reduce exposure to supply chain attacks.

Security News
Experts push back on new claims about AI-driven ransomware, warning that hype and sponsored research are distorting how the threat is understood.

Security News
Ruby's creator Matz assumes control of RubyGems and Bundler repositories while former maintainers agree to step back and transfer all rights to end the dispute.