Allows to create validation schemas by using typescript decorators using joi as a backend
Status: Work in progress
Table of Contents
- joi-typescript-validator
npm install --save joi-typescript-validator
Invalidates the object if the field doesn't exist
class Example {
@Required()
public field: string;
}
// Joi schema
schema.required();
Turns off the required flag for the field
class Example {
@Optional()
public field: string;
}
// Joi schema
schema.optional();
Allows the field to have null as a value
class Example {
@Nullable()
public field: string;
}
// Joi schema
schema.allow(null);
or...
class Example {
@Nullable()
public field: string;
}
class Derived extends Example {
/**
* Use it with a boolean value if you need to disable the value on
* a derived class
* */
@Nullable(false)
public field: string;
}
Allows only the values provided in the arguments
class Example {
@ValidOptions("name", "age")
public field: string;
}
// Joi schema
schema.valid("name", "age");
Specifies the max value for the field
class Example {
@Max(42)
public field: number;
}
// Joi schema
schema.max(42);
or...
class Example {
/**
* Excludes the value from being accepted
* */
@Max({ value: 42, exclude: true })
public field: number;
}
// Joi schema
schema.max(42).invalid(42);
Specifies the min value for the field
class Example {
@Min(42)
public field: number;
}
// Joi schema
schema.min(42);
or...
class Example {
/**
* Excludes the value from being accepted
* */
@Min({ value: 42, exclude: true })
public field: number;
}
// Joi schema
schema.min(42)
Allows positive values only to the number field
class Example {
@Positive()
public field: number;
}
// Joi schema
schema.positive();
class Derived extends Example {
// Use the flags if you need to override it when you inherit
@Positive(false)
public field: number;
}
Allows negative values only to the number field
class Example {
@Negative()
public field: number;
}
// Joi schema
schema.negative();
class Derived extends Example {
// Use the flags if you need to override it when you inherit
@Negative(false)
public field: number;
}
Sets a lower limit to the string length
class Example {
@MinLength(42)
public field: string;
}
// Joi schema
schema.min(42);
Sets an upper limit to the string length
class Example {
@MaxLength(42)
public field: string;
}
// Joi schema
schema.max(42);
Sets the string lower limit to 1 character
class Example {
@NotEmpty()
public field: string;
}
// Joi schema
schema.min(1);
class Derived extends Example {
// Use the flag if you want to disable the NotEmpty check on a derived class
@NotEmpty(false)
public field: string;
}
String field should be a valid email
class Example {
@Email()
public field: string;
}
// Joi schema
schema.email();
class Derived extends Example {
// Use the flag if you want to disable the Email check on a derived class
@Email(false)
public field: string;
}
Validates the string as a date using the specified format
class Example {
// Default is YYYY-MM-DD
@Required()
@DateString("YY-MM-DD")
public date: string;
}
// Joi schema
schema.date("YY-MM-DD");
Is required to specify the array item type if the array items should be validated
class Item {
@Required()
public id: number;
}
class Example {
@ItemType(Item)
public field: Item[];
}
// Joi schema
schema.array().items(Joi.object().keys({
id: Joi.number().required(),
}));
Sets a lower limit to the array length
class Example {
@MinLength(42)
public field: string[];
}
// Joi schema
schema.array().min(42);
Sets an upper limit to the array length
class Example {
@MaxLength(42)
public field: string[];
}
// Joi schema
schema.array().max(42);
Sets the array lower limit to 1 item
class Example {
@NotEmpty()
public field: string[];
}
// Joi schema
schema.array().min(1);
class Derived extends Example {
// Use the flag if you want to disable the NotEmpty check on a derived class
@NotEmpty(false)
public field: string[];
}
Specifies the format that the field should have as an input Uses joi-date-extensions Extension as a backend
class Example {
@Required()
@DateString("YYYY-MM-DD")
public date: Date;
}
// Joi schema
Joi.date().format("YYYY-MM-DD").required();
You can create a custom Joi schema for the field or append properties to existing one
// Using a lambda function
class Example {
@Required()
@CustomSchema((current: Joi.Schema) => current.optional())
public field: string;
}
// Creating a schema from scratch, overrides any pre-built schema from other decorators
class SecondExample {
@CustomSchema(Joi.string().optional())
public date: Date;
}
Validates the child fields if their type is another class
class ChildObject {
@Optional()
id: number;
}
class Example {
@Required()
public child: ChildObject;
}
// Joi schema
schema.object().keys({
child: Joi.object().keys({
id: Joi.number().optional(),
}).required(),
});
Inherited classes inherit the validation metadata from the base class
class BaseObject {
@Optional()
id: number;
}
class Inherited extends BaseObject {
@Optional()
name: string;
}
// Joi schema
schema.object().keys({
id: Joi.number().optional(),
name: Join.string().optional(),
});
You can also override validation properties from the base class
class BaseObject {
@Required()
@Email()
primary: string;
}
class Inherited extends BaseObject {
@Optional()
name: string;
@Optional()
primary: string;
}
// Joi schema
// Base Class
schema.object().keys({
primary: Joi.string().email().required(),
});
// Derived Class
schema.object().keys({
primary: Joi.string().email().optional(),
name: Join.string().optional(),
});
import { getSchema } from "joi-typescript-validator"
class Example {
@Required()
@Email()
email: string;
}
const schema: Joi.Schema = getSchema(Example);
import { Validate } from "joi-typescript-validator"
class Example {
@Required()
@Email()
public email: string;
}
const value: Example = new Example();
value.email = "john@example.com";
Validate(Example, value).catch((error) => { console.log(error.message) });
import { Validate } from "joi-typescript-validator"
class UserData {
@Optional()
allowNotifications: boolean;
}
class Location {
@Required()
@NotEmpty()
name: string;
@Required()
latitude: number;
@Required()
longitude: number;
}
class User {
@Required()
@Email()
public email: string;
@Required()
@MaxLength(30)
@MinLength(5)
public username: string;
@Required()
@MaxLength(30)
@MinLength(5)
public password: string;
@Optional()
@Min({ value: 18 })
@Max({ value: 30, exclude: true })
public age: number;
@Required()
public data: UserData;
@Required()
@ItemType(Location)
@MaxLength(10)
public locations: Location[];
}
async function fetchData(): Promise<User> {
...
}
fetchData().then((result: User) => Validate(User, user));