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.
Looking for every exported function? Check out the full export reference.
- Introduction
- Benchmarks
- Installation
- Basic Validators
- Complex Validators
- Utilities
- Object Schema Validation
- Safety Modes
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
import { isOptionalString } from 'jet-validators';
if (isOptionalString(value)) {
// value is string | undefined
}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 |
npm install jet-validatorsBasic validators can be imported directly and used without configuration.
All validators follow consistent naming patterns:
isXisOptionalXisNullableXisNullishXisXArray(and variants)
isUndefisNullisNullish(null | undefined)
isBooleanisOptionalBooleanisNullableBooleanisNullishBooleanisBooleanArray(+ variants)
Valid after running through parseBoolean
isValidBooleanisOptionalValidBooleanisNullableValidBooleanisNullishValidBooleanisValidBooleanArray(+ variants)
isNumber(+ optional / nullable / array variants)
Sub-categories:
- Positive
- Negative
- Unsigned
Each includes the full optional / nullable / array variants.
Same structure as isNumber, including:
- Positive
- Negative
- Unsigned
isBigIntisOptionalBigIntisNullableBigIntisNullishBigIntisBigIntArray(+ variants)
Valid after numeric coercion.
isValidNumberisOptionalValidNumberisNullableValidNumberisNullishValidNumberisValidNumberArray(+ variants)
isString(+ optional / nullable / array variants)
Ensures .length > 0.
isNonEmptyString(+ variants)
isSymbol(+ variants)
Checks for a Date instance with a valid timestamp.
!isNaN(date.getTime())isDate(+ variants)
Accepts Date, string, or number and validates via new Date(...).
isValidDate(+ variants)
Is non-nullable object
isObject(+ variants)
Is it an object of type Record<string, unknown> and nothing else (i.e. Date, Array, etc).
isPlainObject(+ variants)
isFunction(+ variants)
These require an initialization step and return a validator function.
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. |
| 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. |
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 | undefinedPlease see the test isValidString for a full example.
const isAllowed = isInArray(['a', 'b', 'c']);
isAllowed('a'); // trueSupports optional / nullable variants.
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.
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'); // trueconst negative = isInRange([], 0);
negative(-1); // trueconst outside = isInRange(100, 50);
outside(101); // true
outside(75); // falseChecks whether a value is a key of an object.
const obj = { foo: 'bar', baz: 'qux' } as const;
const isKey = isKeyOf(obj);
isKey('foo'); // trueNote: Does not support symbol keys.
Checks whether a value exists in an object.
const obj = { foo: 'bar', baz: 'qux' } as const;
const isValue = isValueOf(obj);
isValue('bar'); // trueIncludes the ValueOf<T> utility type.
Utilities are imported from:
import { parseObject } from 'jet-validators/utils';Removes null and undefined from a validator.
const isStrictString = nonNullable(isNullishString);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"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.
Converts common boolean representations to actual booleans:
"true","false"(case-insensitive)"1","0"1,0
parseBoolean('TrUe'); // true
parseBoolean(0); // falseSafely wraps JSON.parse.
const nums = parseJson<number[]>('[1,2,3]');Throws if input is not a string.
Extremely fast and lightweight schema validation for objects using validator functions.
These utilities are intentionally simpler than libraries like Zod or AJV.
- 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
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. |
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"]
}]Same behavior as parseObject, but returns a type predicate.
if (testUser(user)) {
// user is IUser
}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,
}),
});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.
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.
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.
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.
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
});