Basic type guards building on helper types from @rickosborne/typical.
Install via your favorite package manager.
Each package supports CommonJS require
, ESM import
, and TypeScript usage.
You also have a choice: barrel imports or direct imports.
Barrel imports mean you're going to require/import everything from the same package-level namespace:
// CommonJS
const { isPlainObject, isListOf } = require("@rickosborne/guard");
// ESM / TypeScript
import { isPlainObject, isListOf } from "@rickosborne/guard";
Implications:
- Nice and simple.
- Your build system needs to do tree-shaking well ... or you'll end up adding the entire package even if you only import two functions.
The other option is to use direct imports:
// CommonJS
const { isPlainObject } = require("@rickosborne/guard/is-object");
const { isListOf } = require("@rickosborne/guard/is-list-of");
// ESM / TypeScript
import { isPlainObject } from "@rickosborne/guard/is-object.js";
import { isListOf } from "@rickosborne/guard/is-list-of.js";
Implications:
- You (probably) don't have to worry about tree-shaking as your build (likely) ends up with only the functions you need.
If you're using a modern build system, there aren't any strong reasons to prefer one way over the other. It's really just down to your personal preference.
Do you need to use file extensions? And if so, which extensions?
Honestly ... this is a dumpster fire question. It really comes down to your own setup and configuration.
Within each package itself:
- The CommonJS files all have
.cjs
extensions. - The ESM files all have
.mjs
extensions. - Node subpath exports have been set up to send
.js
imports to the.cjs
(viarequire
) or.mjs
(viaimport
) files, depending on your setup.
So, in theory, the only extension which won't work would be .ts
because the source isn't included.
If you run into a problem with a particular configuration, file a GitHub issue with:
- Your
tsconfig.json
'smodule
,moduleResolution
, andtarget
settings. - Your
package.json
'stype
andimports
settings. - An example of another package which imports correctly for you.
This package is licensed as CC-BY-NC-SA-4.0 unless otherwise noted. That is, Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International.
class ValidationError extends Error
An error which collects any number of problems encountered while attempting to validate a value against a type schema/guard.
function assertDefined<T>(value: T, messageOrError: MessageOrError): asserts value is NonNullable<T>;
Assert the given value is not null or undefined. Throws with the given message or error, otherwise.
function assertInt(value: unknown, messageOrError: MessageOrError): asserts value is number;
Throw if the given value is not an integer.
function assertJSONArray(value: unknown): asserts value is JSONArray;
Assert the given value could be serialized as a JSON Array.
function assertJSONObject(value: unknown): asserts value is JSONObject;
Assert the given value could be serialized as a JSON Object.
function assertJSONPrimitive(value: unknown): asserts value is JSONPrimitive;
Assert the given value could be serialized as a JSON Primitive.
function assertJSONSerializable(value: unknown): asserts value is JSONSerializable;
Assert the given value could be serialized as JSON.
errorFromMessageOrError: (messageOrError: MessageOrError, defaultConstructor?: (new (message: string) => Error)) => Error
Helper for guards which expect text or an error, or can generate one when needed.
expectDefined: <T>(obj: T, messageOrError: MessageOrError) => NonNullable<T>
Coerce a value's type to exclude null or undefined, or throw if it actually is null or undefined.
expectInt: (obj: unknown, messageOrError: MessageOrError) => number
Coerce a value's type to a number, throwing if it's not an integer.
formatValidationProblem: (problem: ValidationProblem) => string
function hasArray<Name extends string>(obj: unknown, name: Name, predicate?: undefined): obj is {
[K in Name]: unknown[];
};
Guard for whether the given value is an object which has a property with its own array value. This variant does not exhaustively check the items of the array.
function hasArray<Name extends string, Item>(obj: unknown, name: Name, predicate?: (item: unknown, index: number, items: unknown[]) => item is Item): obj is {
[K in Name]: Item[];
};
Guard for whether the given value is an object which has a property with its own array value. This variant exhaustively checks the items of the array against the given predicate.
hasNumber: <Name extends string>(obj: unknown, name: Name) => obj is { [k in Name]: number; }
Guard for whether an object has a property with the given name and a numeric value.
hasObject: <Name extends string>(obj: unknown, name: Name) => obj is { [k in Name]: object; }
Guard for whether an object has a property with the given name and an object value.
function hasOptional<Name extends string>(obj: unknown, name: Name): obj is {
[K in Name]?: unknown;
};
Guard for whether the given value is an object with an optional property with the given name. This variant does not check the value, only that the property exists.
function hasOptional<Name extends string, T>(obj: unknown, name: Name, predicate: (value: unknown) => value is T): obj is {
[K in Name]?: T;
};
Guard for whether the given value is an object with an optional property with the given name. This variant checks the value against the given predicate.
function hasOwn<Name extends string | symbol>(obj: unknown, name: Name): obj is {
[K in Name]: unknown;
};
Guard for whether the given value is an object with a property with the given name. This variant does not check the value, only that the property exists.
function hasOwn<Name extends string | symbol, T>(obj: unknown, name: Name, predicate: (value: unknown) => value is T): obj is {
[K in Name]: T;
};
Guard for whether the given value is an object with a property with the given name. This variant checks the value against the given predicate.
hasPlainObject: <Name extends string>(obj: unknown, name: Name) => obj is { [k in Name]: Record<never, never>; }
Guard for whether an object has a property with the given name and a plain object value.
hasString: <Name extends string>(obj: unknown, name: Name) => obj is { [k in Name]: string; }
Check whether the given value is an object, has a property with the given name, and the value of that property is a string.
isAsyncIterableLike: <T = unknown>(value: unknown) => value is AsyncIterable<T>
isDefined: <T>(obj: T) => obj is NonNullable<T>
Guard to filter out null or undefined values.
isDigit: (value: unknown) => value is Digit
isHexDigit: (value: unknown) => value is HexDigit
isInt: (obj: unknown) => obj is number
Check whether the given value is not just numeric, but is also an integer.
isIterableLike: <T = unknown>(value: unknown) => value is Iterable<T>
isIteratorLike: <T = unknown>(value: unknown) => value is Iterator<T, unknown, unknown> | AsyncIterator<T, unknown, unknown>
function isJSONArray(value: unknown): value is JSONArray;
Type guard testing whether the value could be serialized as a JSON Array without losing information.
function isJSONObject(value: unknown): value is JSONObject;
Type guard for values which could be serialized as JSON Objects.
function isJSONPrimitive(value: unknown): value is JSONPrimitive;
Type guard validating the value could be serialized as a JSON primitive.
function isJSONSerializable(value: unknown): value is JSONSerializable;
Type guard for any value which could be serialized natively as JSON.
isListOf: <T>(list: unknown, predicate: (item: unknown, index: number, items: unknown[]) => item is T) => list is T[]
Guard to check if the given value is an array where all the items match the given predicate.
isObject: (obj: unknown) => obj is NonNullable<object>
Guard to check that the given value is defined and object-like.
isPlainObject: (obj: unknown) => obj is Record<never, never>
Guard to check that the given value is defined, is an object, and seems to be a "plain" object, descending directly from Object. This won't prevent all shenanigans, but is a low-effort check.
isPromiseLike: <T = unknown>(value: unknown) => value is PromiseLike<T>
Type guard for a Promise-like "thenable".
isString: (value: unknown) => value is string
Type guard for a string value. Just calls typeof
, but could make complicated type guard compositions easier to read.
isUnaryPredicate: (obj: unknown) => obj is UnaryPredicate<unknown>
Tests whether the given object is a function and takes at least one parameter, and could maybe act as a unary predicate. Warning! Since no type information is available at runtime, it may not actually act as a predicate!
maybeInt: (text: string) => number | undefined
Convert to an integer, if it seems like it could be done safely. See decimal separator on Wikipedia for details on how this is probably very wrong in many countries.
function scrubStackTrace<E extends Error>(err: E, removeIf?: StackRemoveIf | undefined): E;
Wrap an Error in a proxy which cleans up the stack trace to be more human-readable. It filters out lines from third-party code, so you can quickly see your own code in the call stack. May optionally include some way of indicating additional lines which should be removed, so a guard function could make itself transparent, making it seem like the caller threw the error.
function scrubStackTrace(stack: string | undefined, removeIf?: StackRemoveIf | undefined): string | undefined;
function validateJSONArray(value: unknown, seen?: Map<unknown, ValidationProblem[]>, path?: string[]): ValidationProblem[];
Try to validate the given value's items could be serialized as a JSON Array without losing information. An empty result array implies the value is a valid JSON Array.
function validateJSONObject(value: unknown, seen?: Map<unknown, ValidationProblem[]>, path?: string[]): ValidationProblem[];
Try to validate the given value could be serialized as a JSON Object without losing information. An empty result array means the value is a valid JSON Object.
function validateJSONPrimitive(value: unknown, path?: string[]): ValidationProblem[];
Try to validate the given value could be serialized as a JSON literal primitive without losing information. An empty result array implies the value is a valid JSON primitive.
function validateJSONSerializable(value: unknown, seen?: Map<unknown, ValidationProblem[]>, path?: string[]): ValidationProblem[];
Try to validate that the given value could be serialized correctly as JSON without losing information. An empty result array implies the value is valid JSON.
export interface ThrowOnError
Mixin added to function call options to indicate whether it should throw, or silently swallow the error.
export interface ValidationErrorOptions extends ErrorOptions
export interface ValidationProblem
A problem encountered while attempting to validate a value against a type guard/schema.
type Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
type HexDigit = Digit | "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f";
type MessageOrError = string | Error | (() => (string | Error));
A message, an error, or something which can generate one of those.
type StackRemoveIf = Predicate<string> | RegExp | string;
Specifier for which lines of a stack trace should be removed.
NO_THROW: Readonly<{
readonly throwOnError: false;
}>
Value of ThrowOnError which will avoid throwing.
notPlainObject: unique symbol
A symbol which can be exposed when you want isPlainObject to be false for an object. It doesn't matter what the value is.