Skip to content

Extensible schema based validator that supports typescript typing.

License

Notifications You must be signed in to change notification settings

winestone/validate-typescript

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Validate Typescript

Simple and extensible schema based validator with support for typescript typing.

test

npm version npm license npm downloads/week

github issues github lsat commit

github languages github code size

Getting Started

The example below represents a basic subset of the inline validations that can be applied.

Example

import { Email, ID, RegEx, Type, Options, Optional, Nullable, Alias, Any, All, validate } from 'validate-typescript';

function ZaPhoneNumber() {
    return Alias(RegEx(/^((\+27|0)\d{9})$/), ZaPhoneNumber.name);
}

class CustomMessage {
    constructor(public message: string) {}
}

const schema = {
    id: ID(),
    children: [ID()],
    username: Type(String),
    email: Email(),
    gmail: RegEx(/.+@gmail.com/),
    phone: ZaPhoneNumber(),
    gender: Options(['m', 'f', 'o']),
    married: Type(Boolean),
    names: {
        first: Type(String),
        middle: Optional(Type(String)),
        last: Type(String)
    }
    message: Type(CustomMessage)
}

const input = {
    id: 17,
    children: [1,2,'3'],
    username: 'solomon',
    email: 'solomon@validate-typescript.com',
    gmail: 'solomon@gmail.com',
    phone: '+27824392186'
    gender: 'm',
    married: true,
    names: {
        first: 'Solomon',
        last: 'Dube',
    }
    message: new CustomMessage('Sawubona Mhlaba')
}

try {
    const input = validate(schema, input);
    console.log(input); // no validation error
} catch (error) {
    console.log(error); // validation error
}

Installation

npm install validate-typescript

Imports

The default import provides validate, all the validators and all the extensions:

import { ... } from 'validate-typescript';

Validators

The following examples of validate-typescript schemas illustrate the different validation methods.

Note: the comment // type: TypeName following the validator explicitly specifies the resultant typescript type inferred by the typescipt transpiler. This relates back to the strongly typed criteria.

Type Validators

Expects an exact type match.

let schema = {
    myNumber: Type(Number),      // type: Number
    myString: Type(String),      // type: String
    myCustom: Type(CustomClass), // type: CustomClass
    // etc...
}

Primitive Validators

Expects an exact primitive type match.

let schema = {
    myNumber: Primitive(Number),      // type: number
    myString: Primitive(String),      // type: string
    // etc...
}

Literal Validators

Expects an exact type and value match.

let schema = {
    number49:    49,              // type: number
    myCountry:   'South Africa',  // type: string
    dontDefine:  undefined,       // type: undefined
    allwaysNull: null,            // type: null
    // etc...
}

Custom (Extension) Validators

Expects custom convertions and assertions to be valid.

let schema = {
    myEmail:  Email(),      // type: string
    sqlId:    ID(),         // type: number
    comeText: RegEx(/abc/), // type: string
    // etc...
}

Nested Object Validators

Expects a nested object that matches the nested schema.

let schema = {
    subObject: {
        a: ID(),
        b: Type(Date)
        c: {
            d: RegEx(/.+@gmail.com/)
        }
    } // type: { a: number, b: Date, c: { d: string } }
}

Array Validators

Expects an array that matches the contents of the array schema.

Note: Multiple validators in the array are treated as boolean-or (any).

let schema = {
    // array validation
    emailArray: [Email()]             // type: string[]
    idArray: [ID()]                   // type: number[]

    // array with multiple options validation
    arrayOfEmailOrId: [Email(), ID()] // type: (string | number)[]
}

Options Validators

Expects any or all of the validation options to match.

let schema = {
    // options validation
    options: Options([Type(Number), Type(String)]) // type: number | string

    // optional validation (i.e. not required)
    optional: Optional(ID())                       // type: number | undefined
    alsoOptional: Options([ID(), undefined])       // type: number | undefined

    // nullable validation
    maybeNull: Nullable(Type(String)),             // type: String | null
    alsoMaybeNull: Options([Type(String, null)]),  // type: String | null

    // array options
    arrayOptions: Options([[Email()], [ID()]])     // type: string[] | number[]
}

Any or All Validators

Any represents boolean-or of the validation options while all represents boolean-and.

let schema = {

    // validate any options
    anyOptions: Options([Type(Number), Type(String)], ValidationOptions.any)     // type: number | string
    alsoAny: Any([Type(Number), Type(String)])                                   // type: number | string

    // validate all options
    allOptions: Options([RegEx(/.+@gmail.com/), Email()], ValidationOptions.all) // type: number | string
    alsoAll: All([RegEx(/.+@gmail.com/), Email()])                               // type: number | string
}

Validation

Note: the return of validate, in this case input, will inherit the typescript typing of the schema, thus strongly-typed.

try {
    const input = validate(schema, input);
    console.log(input); // no validation error
} catch (error) {
    console.log(error); // validation error
}

Assertions

Assertions allow enforcing of basic validation conditions and form the atomic building blocks of custom validators. Upon failure, assertions throw an AssertionError.

Note: All assertions take a flag allowing conditional inversion.

Assertions are intended to be extended.

Typed Assertions

Assertion Description
isSameType Assert type equality of two inputs.
isSameTypeName Asserts type name equality of two inputs.
isSymbol Asserts symbol type input.
isBoolean Asserts boolean type input.
isString Asserts string type input.
isNumber Asserts number type input.
isArray Asserts array type input.
isNull Asserts null type input.
isObject Asserts object type input.
isUndefined Asserts undefined type input.

Numeric Assertions

Assertion Description
isInt Asserts integer input.
isFloat Asserts float input.

Operational Assertions

Assertion Description
isEqualTo Asserts equality (==) of two inputs.
isGreaterThan Asserts greater than relation (>) of two inputs.
isLessThan Asserts less than relation (<) of two inputs.
isGreaterThanOrEqualTo Asserts greater than or equal to relation (>=) of two inputs.
isLessThanOrEqualTo Asserts less than or equal to relation (<=) of two inputs.

Misc Assertions

Assertion Description
isEqual Asserts typed equality (===) of two inputs.
isRegEx Asserts RegExp matching input.

Converters

All converters attempt to convert the input to a specific type and throw a ConversionError if the conversion fails.

Converters are intended to be extended.

Conversion Output Type Input Types Description
toInt number number, string Converts only integers (needs updating)
toNumber number number, string Converts any number
toBoolean boolean boolean, string Converts 'true' and 'false' (needs updating)

Errors

Custom validation errors are implemented. It is ulikely that you will need to extend these but there may be future extensions.

  • ValidationError: Abstract base class for all validation errors.
  • ConversionError: Type of all the conversion errors.
  • AssertionError: Type of all the assertion errors.
  • ValidationError: Type of all the validation errors.
  • NotMatchAnyError: Type of error thrown when Any does not match any of the provided validation options.

For example, supporting JSON formatted validation errors for easier parsing and logging.

Custom Validators (Extensions)

Validators can be customized using converters, assertions as well as other custom validators (extensions). Upon failure, validators throw a ValidationError.

Alias

Aliasing is a method of aliasing a custom validator, possibly with inputs.

import { RegEx, Alias } from 'validate-typescript';

export function ZaPhoneNumber() {
    return Alias(RegEx(/^((\+27|0)\d{9})$/), ZaPhoneNumber.name);
}

ID

This example illustrates the use of both a converter and an assertion.

import { Validator } from 'validate-typescript';
import * as convert from 'validate-typescript/conversions';

export function ID() {
    return Validator((input: any): number => {
        const value = convert.toInt(input);
        assert.isGreaterThan(0, value);
        return value;
    }, ID.name);
}

RegEx

This example illustrates only the use of assertions.

import { Validator } from 'validate-typescript';
import * as assert from 'validate-typescript/assertions';

export function RegEx(regEx: RegExp) {
    return Validator((input: any): string => {
        assert.isString(input);
        assert.isRegEx(regEx, input);
        return input;
    }, RegEx.name);
}

About

Extensible schema based validator that supports typescript typing.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 100.0%