Package Exports
- jet-validators
- jet-validators/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (jet-validators) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
jet-validators 🧑✈️
A list common TypeScript validator-functions and some useful utilities to go with them.
Table of Contents
Introduction
A simple, but long, list of validator-functions commonly used when checking values in TypeScript. This is not meant to replace advanced schema validation libraries like zod, valibot, jet-schema etc. This is just a list of pre-defined validator-functions to save you time and boilerplate code in TypeScript.
Quick Glance
import { isOptionalString, isRecord } from 'jet-validators';
if (isOptionalString(val)) {
// val is string | undefined
}
if (isRecord(val)) {
val['foo'] = 'bar';
}Why jet-validators
- Contains validator-functions for the vast majority of real world scenarios you will encounter.
- For basic validators, there's no initialization step, you just import the validator-function and start using it.
- Overload regular expressions using environment variables.
- Contains some useful utilities for modifying values before validation.
- Also has some utilities for simple object schema validation.
- Zero dependency!
Installation
npm i -s jet-validatorsBasic Validators
These can be imported and used directly and don't require any configuration.
Nullables
- isUndef
- isNull
- isNullOrUndef
isBoolean
- isBoolean
- isOptionalBoolean
- isNullableBoolean
- isNullishBoolean
- isBooleanArray
- isOptionalBooleanArray
- isNullableBooleanArray
- isNullishBooleanArray
isValidBoolean
Is it a valid boolean after calling the parseBoolean utility function.
- isValidBoolean
- isOptionalValidBoolean
- isNullableValidBoolean
- isNullishValidBoolean
- isValidBooleanArray
- isOptionalValidBooleanArray
- isNullableValidBooleanArray
- isNullishValidBooleanArray
isNumber
- isNumber
- isOptionalNumber
- isNullableNumber
- isNullishNumber
- isNumberArray
- isOptionalNumberArray
- isNullableNumberArray
- isNullishNumberArray
isBigInt
- isBigInt
- isOptionalBigInt
- isNullableBigInt
- isNullishBigInt
- isBigIntArray
- isOptionalBigIntArray
- isNullableBigIntArray
- isNullishBigIntArr
isValidNumber
- isValidNumber
- isOptionalValidNumber
- isNullableValidNumber
- isNullishValidNumber
- isValidNumberArray
- isOptionalValidNumberArray
- isNullableValidNumberArray
- isNishValidNumArr
isString
- isString
- isOptionalString
- isNullableString
- isNullishString
- isStringArray
- isOptionalStringArray
- isNullableStringArray
- isNullishStringArray
isNonEmptyString
- isNonEmptyString
- isOptionalNonEmptyString
- isNullableNonEmptyString
- isNullishNonEmptyString
- isNonEmptyStringArray
- isOptionalNonEmptyStringArray
- isNullableNonEmptyStringArray
- isNullishNonEmptyStringArray
- TNonEmptyStr
isSymbol
- isSymbol
- isOptionalSymbol
- isNullableSymbol
- isNullishSymbol
- isSymbolArray
- isOptionalSymbolArray
- isNullableSymbolArray
- isNullishSymbolArray
isDate
- isDate
- isOptionalDate
- isNullableDate
- isNullishDate
- isDateArray
- isOptionalDateArray
- isNullableDateArray
- isNullishDateArray
isValidDate
Is it a valid date after wrapping with new Date() (could be Date, string, number)
- isValidDate
- isOptionalValidDate
- isNullableValidDate
- isNullishValidDate
- isValidDateArray
- isOptionalValidDateArray
- isNullableValidDateArray
- isNullishValidDateArray
isObject
- isObject
- isOptionalObject
- isNullableObject
- isNullishObject
- isObjectArray
- isOptionalObjectArray
- isNullableObjectArray
- isNullishObjectArray
isRecord
Checks if the argument is a non-null non-array object. Type predicate is Record<string, unknown>.
- isRecord
- isOptionalRecord
- isNullableRecord
- isNullishRecord
- isRecordArray
- isOptionalRecordArray
- isNullableRecordArray
- isNullishRecordArray
- TRecord (type)
isFunction
- isFunction
- isOptionalFunction
- isNullableFunction
- isNullishFunction
- isFunctionArray
- isOptionalFunctionArray
- isNullableFunctionArray
- isNullishFunctionArray
Regular Expressions
Verifies the argument matches the regular-expression. Note than an empty string will validate to true for each function.
Overloading with environment variables
The regular expressions for each function below can be overwritten using the environment variables. To overload a regular expression create an environment variables with the format:
- JET_VALIDATORS_REGEX_{name of the function in uppercase} (i.e.
JET_VALIDATORS_REGEX_EMAIL=^\S+@\S+\.\S+$)
isColor
- isColor
- isOptionalColor
- isNullableColor
- isNullishColor
- TColor (type)
isEmail
- isEmail
- isOptionalEmail
- isNullableEmail
- isNullishEmail
- TEmail (type)
isUrl
- isUrl
- isOptionalUrl
- isNullableUrl
- isNullishUrl
- TURL (type)
isAlphaNumericString
- isAlphaNumericString
- isOptionalAlphaNumericString
- isNullableAlphaNumericString
- isNullishAlphaNumericString
- TAlphabeticStr (type)
isAlphabeticString
- isAlphabeticString
- isOptionalAlphabeticString
- isNullableAlphabeticString
- isNullishAlphabeticString
- TAlphaNumericStr (type)
Complex Validators
These require an initialization step which will return a validator function.
isInArray
- isInArray
- isOptionalInArray
- isNullableInArray
- isNullishInArray
Does the argument strictly equal any item in the array:
const isInArrTest = isInArray(['1', '2', '3']);
isInArrTest('1'); // => trueisInRange
- isInRange
- isOptionalInRange
- isNullableInRange
- isNullishInRange
- isInRangeArray
- isOptionalInRangeArray
- isNullableInRangeArray
- isNullishInRangeArray
Will check if the argument (can be a number-string or a number) is in the provided range. The function will check if the argument is greater-than the first param and less-than the second param. If you wish to include the min or max value in the range (i.e. greater-than-or-equal-to) wrap it in square brackets. If you wish to leave off a min or max pass an empty array []. If you want to check if the number is not between two numbers, use the bigger number for the first param and the lesser number for the second:
// Between 0 and 100
const isBetween0And100 = isInRange(0, 100);
isBetween0And100(50); // false
isBetween0And100('100'); // false
isBetween0And100(0); // true
// Is negative
const isNegative = isInRange([], 0);
isNegative(0); // false
isNegative(-.0001); // true
const isOptPositive = isOptionalInRange(0, []);
isOptPositive(undefined); // true
isOptPositive(1_000_000_000); // true
// 0 to 100
const isFrom0to100 = isInRange([0], [100]);
isFrom0to100('50'); // true
isFrom0to100(100); // true
isFrom0to100(0); // true
// less than 50 or greater than 100
const lessThan50OrGreaterThan100 = isInRange(100, 50);
lessThan50OrGreaterThan100(75); // false
lessThan50OrGreaterThan100(101); // trueisKeyOf
- isKeyOf
- isOptionalKeyOf
- isNullableKeyOf
- isNullishKeyOf
- isKeyOfArray
- isOptionalKeyOfArray
- isNullableKeyOfArray
- isNullishKeyOfArray
Checks if the argument is a key of the object. Note that this will not work for symbols:
const someObject = {
foo: 'bar',
bada: 'bing',
} as const;
const isKeyofSomeObject = isKeyOf(someObject);
isKeyofSomeObject('foo'); // true
const isKeyofSomeObjectArr = isNullableKeyOfArray(someObject);
isKeyofSomeObjectArr(['bada', 'foo']); // trueisEnum
- isEnum
- isOptionalEnum
- isNullableEnum
- isNullishEnum
- TEnum (type)
Check if the argument is a valid enum object. Unlike other complex validators, this does not require an inialization step. Note this will not work for mixed enum types: see: eslint@typescript-eslint/no-mixed-enums:
enum StringEnum {
Foo = 'foo',
Bar = 'bar',
}
isEnum(StringEnum) // trueisEnumVal
- isEnumVal
- isOptionalEnumVal
- isNullableEnumVal
- isNullishEnumVal
Check if the argument is a value of the enum. You must initialize this with a valid non-mixed enum type: see: eslint@typescript-eslint/no-mixed-enums:
enum NumberEnum {
Foo,
Bar,
}
const isNumberEnumVal = isEnumVal(NumberEnum);
isNumberEnumVal(NumberEnum.Foo); // trueUtilities
These complement the validator-functions and are useful if you need to modify a value before checking it or validate an object's schema. Utilities need to be imported using /utils at the end of the library name:
import { parseObject } from 'jet-validators/utils';Simple Utilities
nonNullable
Remove null/undefined from type-predicates and runtime validation:
const isString = nonNullable(isNullishString);
isString(null); // false
isString(undefined); // falseiterateObjectEntries
Loop through and object's key/value pairs and fire a callback for each one. If any callback returns false, the whole function will return false. It will also caste the return value to the generic if passed one. Note that this does not work recursively. This function is useful for dynamic objects where you don't know what the keys will be:
const isStrNumObj = iterateObjectEntries<Record<string, number>>((key, val) =>
isString(key) && isNumber(val));
isStrNumObj({ a: 1, b: 2, c: 3 }); // true
isStrNumObj({ a: 1, b: 2, c: 'asdf' }); // falsetransform
Accepts a transformation function for the first argument, a validator for the second, and returns a validator-function which calls the transform function before validating. The returned validator-function provides a callback as the second argument, if you need to access the transformed value. You should use transform if you need to modify a value when using parseObject or testObject:
const isNumArrWithParse = transform((arg: string) => JSON.parse(arg), isNumberArray);
isNumArrWithParse('[1,2,3]', val => {
isNumberArray(val); // true
})); // trueparseBoolean
- parseBoolean
- parseOptionalBoolean
- parseNullableBoolean
- parseNullishBoolean
Converts the following values to a boolean. Note will also covert the string equivalents:
"true" or true:true(case insensitive i.e."TrUe" => true)"false" or false:false(case insensitive i.e."FaLsE" => false)"1" or 1:true"0" or 0:false
parseBoolean('tRuE'); // true
parseBoolean(1) // true
parseBoolean('0') // falseparseJson
- parseJson
- parseOptionalJson
- parseNullableJson
- parseNullishJson
Calls the JSON.parse function, if the argument is not a string an error will be thrown:
const numberArr = parseJson<number[]>('[1,2,3]');
isNumberArray(val); // trueValidating object schemas
If you need to validate an object schema, you can pass a validator object with the key being a property of the object and the value being any of the validator-functions in this library OR you can write your own validator-function (see the Custom Validators section).
These functions aren't meant to replace full-fledged schema validation libraries (like zod, ajv, etc), they're just meant as simple object validating tools where using a separate schema validation library might be overkill. If you need something more powerful, I highly recommend this repo's sister library jet-schema which allows you to do a lot more like force schema properties using predefined types.
parseObject
- parseObject
- parseOptionalObject
- parseNullableObject
- parseNullishObject
- parseObjectArray
- parseOptionalObjectArray
- parseNullableObjectArray
- parseNullishObjectArray
This function iterates an object (and any nested object) and runs the validator-functions against each property. If every validator-function passed, the argument will be returned while purging any properties not in the schema. If it does not pass, then the function returns undefined. You can optionally pass a error-handler function as the second argument which will fire whenever a validator-function fails. If the validator-function throws an error, it will be passed to the caughtErr param (see below snippet):
interface IUser {
id: number;
name: string;
address: {
city: string;
zip: number;
}
}
const parseUser = parseObject({
id: transform(Number, isNumber),
name: isString,
address: {
city: isString,
zip: isNumber,
}
}, (property: string, value: unknown, caughtErr?: unknown) => {
throw Error(`Property "${property}" failed to pass validation.`)
});
const user: IUser = parseUser({
id: '5',
name: 'john',
email: '--',
address: {
city: 'seattle',
zip: 99999,
}
});
// 'user' variable above:
// {
// id: 5,
// name: 'john',
// address: {
// city: 'seattle',
// zip: 99999,
// }
// }- If you use the
parseObjectArraythe error callback handler will also pass the index of the object calling the error function:
const parseUserArrWithError = parseObjectArray({
id: isNumber,
name: isString,
}, (prop, value, index) => {
// index "2" should call the error function.
});
parseUserArrWithError([
{ id: 1, name: '1' },
{ id: 2, name: '2' },
{ id: '3', name: '3' },
]);testObject
- testObject
- testOptionalObject
- testNullableObject
- testNullishObject
- testObjectArray
- testOptionalObjectArray
- testNullableObjectArray
- testNullishObjectArray
Test object is nearly identical to parseObject (it actually calls parseObject under-the-hood) but returns a type-predicate instead of the argument passed. Transformed values and purging non-schema keys will still happen as well:
const user: IUser = {
id: '5',
name: 'john',
email: '--',
address: {
city: 'seattle',
zip: 99999,
}
}
const testUser = testObject(user);
if (testUser(user)) { // user is IUser
// 'user' variable above:
// {
// id: 5,
// name: 'john',
// address: {
// city: 'seattle',
// zip: '99999',
// }
// }
}Custom Validators
For parseObject and testObject you aren't restricted to the validator-functions in jet-validators. You can write your own validator-function, just make sure your argument is unknown and it returns a type predicate:
type TRelationalKey = number;
interface IUser {
id: TRelationalKey;
name: string;
}
// The custom validator-function
const isRelationalKey = (arg: unknown): arg is TRelationalKey => {
return isNumber(arg) && arg >= -1;
}
const parseUser = parseObject({
id: isRelationalKey,
name: isString,
});
const user: IUser = parseUser({
id: 5,
name: 'joe',
});Wrapping parseObject/testObject functions
If you want to wrap the parseObject or testObject functions cause you want to let's say, apply the same error handler to multiple object-validators, you need to import the TSchema type and have your generic extend it:
import { isNumber, isString } from 'jet-validators';
import { parseObject, TSchema } from 'jet-validators/utils';
const customParse = <U extends TSchema>(schema: U) => {
return parseObject(schema, (prop: string) => console.error(prop + ' failed validation'))
}
const parseUser = customParse({ id: isNumber, name: isString });
parseUser({ id: 5, name: 'joe' }); // => { id: 5, name: 'joe' }traverseObject
- traverseObject
- traverseOptionalObject
- traverseNullableObject
- traverseNullishObject
- traverseObjectArray
- traverseOptionalObjectArray
- traverseNullableObjectArray
- traverseNullishObjectArray
Iterate over each key in an object (works recursively too) and fire a callback function for each key/value pair that is reached. This is useful if you need to modify an object before doing something with it. If any key/value pair is an array objects, each of those objects will be iterated over too.
Note that for
parseObjectandtestObjectyou should wrap the validator-function withtransformand not usetraverseObject.traverseObjectis useful when you need to modify an object for some other validator likejasmineorvitest(that's what I use it for).
const convertValidToDateObjects = traverseObject((key, value, parentObj) => {
if (isValidDate(value)) {
parentObj[key] = new Date(value);
} else {
parentObj[key] = 'Invalid Date';
}
});
const result = convertValidToDateObjects({
today: '2024-12-06T23:43:37.012Z',
lastYear: '2023-12-06T22:14:20.012Z',
nested: {
milli: 1733528684737,
invalid: '2024-12-06TVB23:43:37.012Z',
dateArr: [1733528684737, 1733528684737, 1733528684737],
},
});
// 'result' variable above:
// {
// today: new Date('2024-12-06T23:43:37.012Z'),
// lastYear: new Date('2023-12-06T22:14:20.012Z'),
// nested: {
// milli: new Date(1733528684737),
// invalid: 'Invalid Date',
// dateArr: [
// new Date(1733528684737),
// new Date(1733528684737),
// new Date(1733528684737),
// ],
// },
// }