npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

typed-validation

v0.8.2

Published

Validate Objects Against TypeScript Interfaces

Downloads

50

Readme

npm npm npm

Strongly-Typed Validators for TypeScript

(Formerly validate-interface)

Build strongly-typed validators that TypeScript can understand, so that TypeScript can validate that your validator is correct.

Installation

$ npm install --save typed-validation

Note: When using this module in a TypeScript project, 0.8.1 and later versions of this module require TypeScript 2.8 or above.

Basic Usage

Example: check that a value of type any (perhaps from an untrusted source, such as a file) is an object that conforms to an interface called Employee:

// 1) Define the interface
interface Employee {
  name: string;
  roleCode: number;
  completedTraining?: boolean;
  addressPostcode: string;
}

// 2) Define the validator
const employeeValidator: Validator<Employee> = {
  name: isString(minLength(1)),
  roleCode: isNumber(min(1, max(10))),
  completedTraining: optional(isBoolean()),
  addressPostcode: isString(matches(/^[a-z]{2}\d{1,2}\s+\d{1,2}[a-z]{2}$/i))
};

// 3) Validate

const unsafeObject: any = {
  name: 'Bob Smith',
  roleCode: 7,
  completedTraining: true,
  addressPostcode: 'AB1 2CD'
};

const result = validate(unsafeObject, conformsTo(employeeValidator));

if (result.success) {
  const bob = result.value;
  const name = bob.name;
}

// Handle errors

const unsafeObject2: any = {
  name: 'Name',
  roleCode: 4,
  completedTraining: 'false',
  addressPostcode: 'WRONG'
};

const result2 = validate(unsafeObject2, conformsTo(employeeValidator));

if (!result2.success) {
  console.log(result2.toString());
}
// Outputs:
// 2 validation errors:
//   $.completedTraining: Expected boolean, got string
//   $.addressPostcode: Failed regular expression /^[a-z]{2}\d{1,2}\s+\d{1,2}[a-z]{2}$/i

Overview

Validators are built by combining simple assertions using function composition and higher-order functions. For example, the isString() assertion returns a function which accepts a single argument of type any and returns either a SuccessResult<string> or an ErrorResult. It will return SuccessResult<string> if and only if the argument is a string, or an ErrorResult otherwise. This module provides a number of assertions, described below.

An assertion may take another assertion as its last argument; if assertion check passes, it calls the next assertion. For example, isString(minLength(1, maxLength(10))) first checks if the value is a string, then checks if its length is at least 1, and then checks that its length is no more than 10. If isString fails, minLength isn't run. Chaining assertions in this way allows for complex validation of types and values.

Some assertions require other assertions to come before it. For example, minLength can't be used by itself because it needs another assertion to check that the value has the length property - so something like isString(minLength(1)) or isArray(minLength(1)).

Jump to section:

Assertions:

validate

The validate function takes two arguments; the first is the argument to validate, the second is an assertion. It returns a result object; if result.success is true, then result.value contains the validated value. If result.success is false, then result.errors contains the list of errors, which can be formatted by calling result.toString().

const result = vaildate(argumentToValidate, isString(minLength(1)));

if (result.success) {
  const validated: string = result.value;
  console.log(`The validated result is: ${validated}`);
} else {
  console.log(`Validation failed: ${result.toString()}`);
}

Handling Validation Errors

When validatin fails, validate will always return an ErrorResult object, which has a property errors: ValidationError[].

The ValidationError type has a number of useful properties:

  • errorCode: A string which is one of a set of error codes, e.g. NOT_STRING. Useful for producing custom error messages or triggering certain error logic.
  • message: A human-readable error message, with more information as to why the validation failed.
  • path: An array of objects that describe the path to the value that caused the validation to fail. Each object is either an ArrayIndexPathNode (which has an index property) or KeyPathNode (which has a key property).

The ErrorResult.toString() method prints this information in a human-readable format. The name of the root object defaults to $, but this can be changed by passing a string, e.g. err.toString('this').

Validator

Validator is a type that enables TypeScript to validate that the validator correctly aligns to the interface it is supposed to validate.

The keys of the validator align with the keys of the interface. The values of the validator are a chain of assertions.

interface IFoo {
  bar: string;
  baz: number;
}

// A valid validator
const fooValidator: Validator<IFoo> = {
  bar: isString(),
  baz: isNumber()
};

// All of these are invalid, and will result in an error from the TypeScript compiler

const fooValidator: Validator<IFoo> = {
  bar: isString()
}; // Missing 'baz'

const fooValidator: Validator<IFoo> = {
  bar: isNumber(), // Wrong type
  baz: isNumber()
};

const fooValidator: Validator<IFoo> = {
  bar: isString(),
  baz: isNumber(),
  blah: isBoolean() // Unexpected property
};

extendValidator

Takes two validators and returns a new validator that validates the intersection type of T and U - useful for extending existing validators to prevent repetition.

Example:

interface IFoo {
  abc: number;
}

const fooValidator: Validator<IFoo> = {
  abc: isNumber()
};

interface IBar extends IFoo {
  xyz: string;
}

const barValidator: Validator<IBar> = extendValidator(fooValidator, {
  xyz: isString()
});

conformsTo

Returns an error if the value does not conform to the given validator.

interface IFoo {
  bar: number;
}

const fooValidator: Validator<IFoo> = {
  bar: isNumber()
};

// Returns a success result
validate({bar: 123}, conformsTo(fooValidator));

// Returns an error result
validate({bar: 'example'}, conformsTo(fooValidator));

The third argument is an optional object of options:

  • allowAdditionalProperties: boolean - If false, returns an error if there are any properties in addition to the ones defined in the validator. Defaults to true, which removes additional properties from the result.
const result1 = validate({foo: 'abc', bar: 123}, conformsTo(fooValidator));

if (result1.success) {
  console.log(result1.value); // {bar: 123}
}

const result2 = validate({foo: 'abc', bar: 123}, conformsTo(fooValidator, {allowAdditionalProperties: false}));

if (!result2.success) {
  console.log(result2.toString())
  // 1 validation error:
  //   $: Unexpected additional properties: foo
}

optional

Used when the properties may not present on the object, or its value is undefined. Example:

interface IFoo {
  bar?: string;
  // You can also use 'undefined' in a union type
  baz: number | undefined;
}

const fooValidator: Validator<IFoo> = {
  bar: optional(isString()),
  baz: optional(isNumber())
};

// Both of these are acceptable
validate({}, conformsTo(fooValidator));
validate({bar: undefined}, conformsTo(fooValidator));

nullable

Used when the value could be null (e.g. prop: T | null).

interface IFoo {
  bar: string | null;
}

const fooValidator: Validator<IFoo> = {
  bar: nullable(isString()),
};

defaultsTo

If the property on the object being validated is undefined, then return the given default value instead.

interface IFoo {
  bar: string;
}

const fooValidator: Validator<IFoo> = {
  bar: defaultsTo('baz', isString()),
};

const result = validate({}, conformsTo(fooValidator));

if (result.success) {
  console.log(result.value);
}

// Output:
// {bar: 'baz'}

Note: the default value will get passed through the assertion chain.

onErrorDefaultsTo

If the following assertion chain fails, then return the given value instead.

interface IFoo {
  bar: string;
}

const fooValidator: Validator<IFoo> = {
  bar: onErrorDefaultsTo('baz', isString()),
};

const result = validate({bar: 123}, conformsTo(fooValidator));

if (result.success) {
  console.log(result.value);
}

// Output:
// {bar: 'baz'}

isBoolean

Returns an error if the value is not a boolean.

isNumber

Returns an error if the value is not a number.

min

Returns an error if the value is less than the given minimum.

interface IFoo {
  bar: number;
}

const fooValidator: Validator<IFoo> = {
  bar: isNuber(min(0))
};

// Returns an error result
const result = validate({bar: -1}, conformsTo(fooValidator));

max

Returns an error if the value is greater than the given maximum - see min.

isString

Returns an error if the value is not a string.

matches

Returns an error if the string value does not match the given regex.

interface IFoo {
  bar: string;
}

const fooValidator: Validator<IFoo> = {
  bar: isStirng(matches(/^[a-z]+$/))
};

// Returns an error result
const result = validate({bar: '123abc'}, conformsTo(fooValidator));

minLength

Returns an error if length of the value (e.g. a string or an array) is less than the given minimum.

interface IFoo {
  bar: string;
}

const fooValidator: Validator<IFoo> = {
  bar: isStirng(minLength(1))
};

// Returns an error result
const result = validate({bar: ''}, conformsTo(fooValidator));

maxLength

Returns an error if length of the value (e.g. a string or an array) is less than the given maximum - see minLength.

lengthIs

Returns an error if length of the value (e.g. a string or an array) is not equal to the given length - see minLength.

isArray

Returns an error if the value is not an array. If no other assertions are given, then the type defaults to any[].

interface IFoo {
  bar: any[];
}

const fooValidator: Validator<IFoo> = {
  bar: isArray()
};

// This is valid
validate({
  bar: ['abc', 123, true, null]
}, conformsTo(fooValidator));

// Returns an error
validate({
  bar: 'baz'
}, conformsTo(fooValidator));

eachItem

Returns an error if any value of an array does not match the following assertion chain.

interface IFoo {
  bar: number[];
}

const fooValidator: Validator<IFoo> = {
  bar: isArray(eachItem(isNumber()))
};

// This is valid
validate({
  bar: [1, 2, 3]
}, conformsTo(fooValidator));

// Returns an error
validate({
  bar: ['abc', 123, true, null]
}, conformsTo(fooValidator));

isObject

Returns an error if the value is not an object.

interface IFoo {
  bar: any;
}

const fooValidator: Validator<IFoo> = {
  bar: isObject()
};

// This is valid, but it wouldn't be safe to access properties on foo.bar
const foo = validate({
  bar: {baz: 123}
}, conformsTo(fooValidator));

// Returns an error
validate({
  bar: 'object'
}, conformsTo(fooValidator));

equals

Returns an error if the value does not equal one of the given values.

type Bar = 'A' | 'B' | 'C';

interface IFoo {
  bar: Bar;
}

const fooValidator: Validator<IFoo> = {
  bar: equals<Bar>('A', 'B', 'C')
};

// Returns an error
validate({
  bar: 'D'
}, conformsTo(fooValidator));

isMap

Validates that the result is a map of string onto any.

interface IFoo {
  map: {[key: string]: any};
}

const fooValidator: Validator<IFoo> = {
  map: isMap()
};

// This is valid
validate({
  map: {
    bar: 'ABC',
    baz: {x: 123, y: 456},
    blah: null
  }
}, conformsTo(fooValidator));

// This is also valid
validate({
  map: { }
}, conformsTo(fooValidator));

// Returns an error - not an object
validate({
  map: 'abc'
}, conformsTo(fooValidator));

// Returns an error - one of the keys is not a string
validate({
  map: {
    bar: 'ABC',
    baz: {x: 123, y: 456},
    0: true
  }
}, conformsTo(fooValidator));

eachValue

Returns an error if any value of a map does not match the following assertion chain.

interface IFoo {
  map: {[key: string]: string};
}

const fooValidator: Validator<IFoo> = {
  map: isMap(eachValue(isString(minLength(1))))
};

// This is valid
validate({
  map: {
    bar: 'ABC',
    'a very long key with spaces': 'DEF'
  }
}, conformsTo(fooValidator));

// Returns an error result
validate({
  map: {
    bar: true, // Not a string
    baz: ''    // Too short
  }
}, conformsTo(fooValidator));

either

Checks against multiple assertions until either one is valid, or they all fail. Useful for complex union types. Assertions are checked in the order given.

When no match is found, all the validation errors for each type are printed.

interface IFoo {
  bar: string | string[];
}

const fooValidator: Validator<IFoo> = {
  bar: either(
    is('a letter', isString(lengthIs(1))),
    is('an array of letters', isArray(eachItem(isString(lengthIs(1)))))
  )
};

// These are valid
validate({bar: 'A'}, conformsTo(fooValidator));
validate({bar: ['A', 'B', 'C']}, conformsTo(fooValidator));

// An invalid example

const result = validate({bar: ['A', 'BC', 'D']}, conformsTo(fooValidator));

if (!result.success) {
    console.log(result.toString());
    // 1 validation error:
    //     $.bar: No match found - the following assertions failed:
    //         Not a letter, due to 1 validation error:
    //             $: Expected string, got array
    //         Not an array of letters, due to 1 validation error:
    //             $[1]: Length 2 is not equal to 1
}

Note: Due to limitations with generics, currently up to 20 assertions are supported by TypeScript.