4.0.2 • Published 5 years ago

validate-typescript v4.0.2

Weekly downloads
692
License
MIT
Repository
github
Last release
5 years ago

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

AssertionDescription
isSameTypeAssert type equality of two inputs.
isSameTypeNameAsserts type name equality of two inputs.
isSymbolAsserts symbol type input.
isBooleanAsserts boolean type input.
isStringAsserts string type input.
isNumberAsserts number type input.
isArrayAsserts array type input.
isNullAsserts null type input.
isObjectAsserts object type input.
isUndefinedAsserts undefined type input.

Numeric Assertions

AssertionDescription
isIntAsserts integer input.
isFloatAsserts float input.

Operational Assertions

AssertionDescription
isEqualToAsserts equality (==) of two inputs.
isGreaterThanAsserts greater than relation (>) of two inputs.
isLessThanAsserts less than relation (<) of two inputs.
isGreaterThanOrEqualToAsserts greater than or equal to relation (>=) of two inputs.
isLessThanOrEqualToAsserts less than or equal to relation (<=) of two inputs.

Misc Assertions

AssertionDescription
isEqualAsserts typed equality (===) of two inputs.
isRegExAsserts 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.

ConversionOutput TypeInput TypesDescription
toIntnumbernumber, stringConverts only integers (needs updating)
toNumbernumbernumber, stringConverts any number
toBooleanbooleanboolean, stringConverts '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);
}
4.0.2

5 years ago

4.0.1

5 years ago

4.0.0

5 years ago

3.0.0

6 years ago

2.0.1

6 years ago

2.0.0

6 years ago

1.9.1

6 years ago

1.9.0

6 years ago

1.8.0

6 years ago

1.7.0

6 years ago

1.6.0

6 years ago

1.5.0

6 years ago

1.4.0

6 years ago

1.1.13

6 years ago

1.1.12

6 years ago

1.1.11

6 years ago

1.1.10

6 years ago

1.1.9

6 years ago

1.1.8

6 years ago

1.1.7

6 years ago

1.1.6

6 years ago

1.1.5

6 years ago

1.1.4

6 years ago

1.1.3

6 years ago

1.1.2

6 years ago

1.1.1

6 years ago

1.1.0

6 years ago

1.0.16

6 years ago

1.0.15

6 years ago

1.0.14

6 years ago

1.0.13

6 years ago

1.0.12

6 years ago

1.0.11

6 years ago

1.0.10

6 years ago

1.0.9

6 years ago

1.0.8

6 years ago

1.0.7

6 years ago

1.0.6

6 years ago

1.0.5

6 years ago

1.0.4

6 years ago

1.0.3

6 years ago

1.0.2

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago