Skip to content

seanpmaxwell/jet-validators

Repository files navigation

jet-validators ✈️

npm downloads types bundle size license

A comprehensive collection of TypeScript validator functions and utilities for common compile and runtime checks.

jet-validator's parseObject function is "JIT optimized" and one of the fastest schema validation tools out there not requiring a compilation step. Check out these benchmarks here.

Table of Contents

Looking for every exported function? Check out the full export reference.


Introduction

jet-validators is a large collection of small, composable validator functions commonly used when validating values in TypeScript.

  • Drop-in validators you can import and use immediately
  • Covers the vast majority of real-world validation needs
  • Extremely fast and lightweight object schema validation
  • Tiny: bundle + zip size only 4.7kb
  • Zero dependencies

Quick Glance

import { isOptionalString } from 'jet-validators';

if (isOptionalString(value)) {
  // value is string | undefined
}

Benchmarks

These results are generated by running npm run build inside ./benchmarks, which executes benchmarks/run-benchmarks.ts to compare parseObject to popular schema validators.

  • Generated: 2026-01-04T00:51:48.812Z
  • Node.js: v24.11.0
  • Dataset size: 1000
  • Iterations per library: 100000
Library Iterations Total Time (ms) Ops/Second
jet-validators 100,000 57.22 1,747,666.4
Zod 100,000 154.1 648,935.23
Joi 100,000 1,275.77 78,383.81
Yup 100,000 2,534.76 39,451.4
Valibot 100,000 275.39 363,124.94

Installation

npm install jet-validators

Basic Validators

Basic validators can be imported directly and used without configuration.

All validators follow consistent naming patterns:

  • isX
  • isOptionalX
  • isNullableX
  • isNullishX
  • isXArray (and variants)

Nullables

  • isUndef
  • isNull
  • isNullish (null | undefined)

isBoolean

  • isBoolean
  • isOptionalBoolean
  • isNullableBoolean
  • isNullishBoolean
  • isBooleanArray (+ variants)

isValidBoolean

Valid after running through parseBoolean

  • isValidBoolean
  • isOptionalValidBoolean
  • isNullableValidBoolean
  • isNullishValidBoolean
  • isValidBooleanArray (+ variants)

isNumber

  • isNumber (+ optional / nullable / array variants)

Sub-categories:

  • Positive
  • Negative
  • Unsigned

Each includes the full optional / nullable / array variants.


isInteger

Same structure as isNumber, including:

  • Positive
  • Negative
  • Unsigned

isBigInt

  • isBigInt
  • isOptionalBigInt
  • isNullableBigInt
  • isNullishBigInt
  • isBigIntArray (+ variants)

isValidNumber

Valid after numeric coercion.

  • isValidNumber
  • isOptionalValidNumber
  • isNullableValidNumber
  • isNullishValidNumber
  • isValidNumberArray (+ variants)

isString

  • isString (+ optional / nullable / array variants)

isNonEmptyString

Ensures .length > 0.

  • isNonEmptyString (+ variants)

isSymbol

  • isSymbol (+ variants)

isDate

Checks for a Date instance with a valid timestamp.

!isNaN(date.getTime())
  • isDate (+ variants)

isValidDate

Accepts Date, string, or number and validates via new Date(...).

  • isValidDate (+ variants)

isObject

Is non-nullable object

  • isObject (+ variants)

isPlainObject

Is it an object of type Record<string, unknown> and nothing else (i.e. Date, Array, etc).

  • isPlainObject (+ variants)

isFunction

  • isFunction (+ variants)

Complex Validators

These require an initialization step and return a validator function.


isValidString

This accepts an options argument and returns a string validator. Unlike most validators this does not have multiple function declarations for the different nullable variants—those are configured on the options argument.

option type description
minLength number Minimum string length. Setting 0 allows '' (empty string) even if regex fails.
maxLength number Maximum string length.
length number Forces exact length (mutually exclusive with minLength/maxLength).
regex RegExp Must pass the given regular expression.
throws boolean Throw instead of returning false on validation failure.
errorMessage (value?: unknown, reason?: string) => string Customize the thrown error message when throws is true.
optional undefined or true Allow undefined inputs.
nullable undefined or true Allow null inputs.
nullish undefined or true Allow both null and undefined.

Restrictions

constraint details
Exclusive lengths Provide either the length field or the minLength/maxLength pair (never both).
Exclusive nullables Use nullish alone, or the optional/nullable pair—those settings are mutually exclusive.
Error customization You can supply errorMessage only when throws is true.

Generics

You can supply a string generic if you want to narrow down the string type:

  const typeValidator3 = isValidString<'foo'>({
    regex: /^foo$/,
    nullish: true,
  });
  // typeValidator3 => arg is 'foo' | null | undefined

Please see the test isValidString for a full example.


isInArray

const isAllowed = isInArray(['a', 'b', 'c']);
isAllowed('a'); // true

Supports optional / nullable variants.


isValidArray

Makes sure that every value in an array, is contained in the validator array. Accepts optional minLength/maxLength arguments as well.

NOTE: this does not validate anything in regards to duplicates. Just that the argument is an array and every value present is allowed.

Please see the test isValidArray for a full example.

Supports optional / nullable variants.


isInRange

Checks whether a number (or numeric string) falls within a range.

Rules:

  • (min, max) → exclusive
  • [min], [max] → inclusive
  • [] → no bound
  • Reverse bounds → “outside range”
const between0and100 = isInRange([0], [100]);
between0and100(50);   // true
between0and100('100'); // true
const negative = isInRange([], 0);
negative(-1); // true
const outside = isInRange(100, 50);
outside(101); // true
outside(75);  // false

isKeyOf

Checks whether a value is a key of an object.

const obj = { foo: 'bar', baz: 'qux' } as const;
const isKey = isKeyOf(obj);

isKey('foo'); // true

Note: Does not support symbol keys.


isValueOf

Checks whether a value exists in an object.

const obj = { foo: 'bar', baz: 'qux' } as const;
const isValue = isValueOf(obj);

isValue('bar'); // true

Includes the ValueOf<T> utility type.


Utilities

Utilities are imported from:

import { parseObject } from 'jet-validators/utils';

nonNullable

Removes null and undefined from a validator.

const isStrictString = nonNullable(isNullishString);

makeOptional / makeNullable / makeNullish

Wrap custom validators to extend their accepted types.

type Email = `${string}@${string}`;

const isEmail = (arg: unknown): arg is Email =>
  isString(arg) && EMAIL_REGEX.test(arg);

const isNullishEmail = makeNullish(isEmail); // --> "Email | null | undefined"

transform

Transforms a value before validation.

const isParsedArray = transform(JSON.parse, isNumberArray);
// isParsedArray is (arg: unknown, (transformedValue: number[]) => void): arg is number[]

Supports callbacks for accessing transformed values.


parseBoolean

Converts common boolean representations to actual booleans:

  • "true", "false" (case-insensitive)
  • "1", "0"
  • 1, 0
parseBoolean('TrUe'); // true
parseBoolean(0);      // false

parseJson

Safely wraps JSON.parse.

const nums = parseJson<number[]>('[1,2,3]');

Throws if input is not a string.


Object Schema Validation

Extremely fast and lightweight schema validation for objects using validator functions.

These utilities are intentionally simpler than libraries like Zod or AJV.


parseObject

  • If valid, returns a full deep clone of the provided object; otherwise returns false.
  • Removes unknown keys (by default)
  • Can enforce strict type-safety on schemas with generics
  • Can infer types from non-generic schemas.
  • Optional error callback
const parseUser = parseObject<IUser>({
  id: transform(Number, isNumber),
  name: isString,
});

Supports:

  • optional / nullable
  • arrays
  • nested schemas
  • loose / strict modes

Error handling

You can pass a callback as the second argument to the parseObject function or the function returned from it which will provide an array of errors if there are any. Each error object has the format:

Field Type Description
info string General information about the validation failure.
functionName string Name of the validator function that failed.
value unknown The value that caused the validation failure (optional).
caught string Error message caught from an unsafe validator function, if any.
key string The key at which the failure occurred but only when it happened at the root level.
keyPath string[] Full path to the failing value for anything other than a key at the rror level. If the failure occurs while inside an array variant (e.g. parseObjectArray), the first element represents the array index of the failing item.

Example

const parseUsersArray = parseObjectArray({ name: isString });
const parseUsersArray([{name: 'sean'}, {name: 123 }], (errors) => ...);

// Errors callback param above will be:
[{
  info: "Validator function returned false.",
  functionName: "isString",
  value: 123,
  keyPath: ["1", "name"]
}]

testObject

Same behavior as parseObject, but returns a type predicate.

if (testUser(user)) {
  // user is IUser
}

Combining parse + test

Nested schemas may use testObject inside parseObject, with caveats around TypeScript inference. Supplying generics restores full type safety. Note you cannot use parseObject on a nested schema because it returns the object being tested not a type-predicate:

  interface IUser {
    id: number;
    name: string;
    address: {
      street: string;
      city: string;
    };
    country?: {
      name: string;
      code: number;
    };
  }

  const parseUser = parseObject<IUser>({
    id: isUnsignedInteger,
    name: isString,

    // **testObject implied** address cannot be undefined
    // and type safety will allow extra keys. Safety is
    // inherited from root `parseUser` function
    address: {
      street: isString,
      city: isString,
    },

    // **testObject explicit** undefined allowed with the
    // optional option and strict type-safety is being
    // enforced
    country: testOptionalObject<IUser['country']>({
      abbreviation: isString,
      name: isString,
    }),
  });

Wrapping parse/test

You may want to wrap a parseObject to let's say, make sure all parse functions throw the same custom Error object. When wrapping these utilities, ensure your generics extend Schema<T> to preserve type safety.

Please see the section Wrapping with Custom Validators around schemas for a full example.


Adding Custom Validators to schemas

Any function of the form (arg: unknown) => arg is T can be used in schemas. If your custom validator checks an object and has nested errors and you want those errors to bubble up to the highest level, you to need to make sure to provide a callback. Other wise parseObject will only see the custom validator itself as the failing function and any nested errors will be ignored.

Please see the section Adding Custom Validators to schemas for a full example.


Manually creating error arrays

If you want to setup your own error array you need to use the setIsParseErrorArray function to mark it as such because in the real world there could be validator functions with callbacks for reasons other than error handling.

Please see the section Manually creating error arrays for a full example.


Getting the type for a "parse/test"Object function

If you need the type for a parse function you created, simply use the utility type ReturnType and pass the typeof "whichever parse function your using" with a generic.

Please see the unit-test Test setting a type for the parseObject for a full example.


Safety Modes

Control how extra object properties are handled. Nested schemas inherit the parent mode unless overridden:

  • loose – keep extra keys
  • default – remove extra keys (no error)
  • strict – remove extra keys and emit errors
const strictUser = strictParseObject({
  address: { street: isString }, // Will inherit strict from parent
  country: looseTestObject(...), // is being overridden
});

About

A list common typescript validator-functions and some useful utilities to go with them.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published