Skip to main content

is.object({ ... })

Validates that a value is a plain object whose fields satisfy the provided shape. Fields not listed in the shape are allowed by default.
import { is } from 'ts-chas/guard';

const PersonGuard = is.object({
  name: is.string.min(1),
  age:  is.number.int.gte(0),
});

PersonGuard({ name: 'Alice', age: 30 });           // true
PersonGuard({ name: 'Alice', age: 30, role: 'admin' }); // true — extra key allowed
PersonGuard({ name: '', age: 30 });                // false

Helpers

.strict — disallows extra keys not listed in the shape.
const Strict = is.object({ id: is.number }).strict;
Strict({ id: 1, extra: true }); // false
.partial — makes all fields optional (T | undefined).
const Patch = is.object({ name: is.string, age: is.number }).partial;
Patch({});           // true — all fields are now optional
Patch({ name: 'x' }); // true
.pick([keys]) — keeps only the listed keys.
const IdOnly = is.object({ id: is.number, name: is.string }).pick(['id']);
IdOnly({ id: 1 });         // true
IdOnly({ id: 1, name: 'x' }); // false — name is an extra key in the narrowed shape
.omit([keys]) — removes the listed keys from the shape.
const NoPassword = is.object({ email: is.string, password: is.string }).omit(['password']);
NoPassword({ email: 'a@b.co' }); // true
.extend({ ... }) — merges additional fields into the shape. Returns a new guard.
const Base  = is.object({ id: is.number });
const Named = Base.extend({ name: is.string });
Named({ id: 1, name: 'Alice' }); // true

is.array(guard?)

Validates that a value is an array. Pass one or more element guards to validate every item.
is.array()([1, 'two', true]); // true — unknown[]
is.array(is.number)([1, 2, 3]); // true — number[]
is.array(is.string, is.number)(['a', 1]); // true — (string | number)[]

Helpers

HelperValidates
.min(n)Length ≥ n
.max(n)Length ≤ n
.length(n)Exact length of n
.nonEmptyLength ≥ 1
const tags = is.array(is.string).nonEmpty.max(10);
tags.parse(['typescript', 'validation']); // Ok(string[])
tags.parse([]);                           // Err(...)

is.record(keyGuard, valueGuard)

Validates that a value is a plain object where every key and value satisfies the provided guards. When keyGuard has a finite set of values (is.enum or is.literal), the record performs exhaustive key checking — all keys must be present and no extra keys are allowed. This matches TypeScript’s Record<'a' | 'b', V> semantics. When keyGuard is open-ended (is.string, is.number), it validates that every existing key/value pair satisfies the guards without requiring any specific keys.
// Open-ended — any string key is fine
const scores = is.record(is.string, is.number);
scores({ alice: 90, bob: 85 }); // true
scores({ alice: 'A' });         // false — value must be number

// Exhaustive — all keys must be present, no extras
const Flags = is.record(is.literal('darkMode', 'beta'), is.boolean);
Flags({ darkMode: true, beta: false }); // true
Flags({ darkMode: true });              // false — 'beta' is missing
.partial makes all enum/literal keys optional.
const PartialFlags = is.record(is.literal('darkMode', 'beta'), is.boolean).partial;
PartialFlags({ darkMode: true }); // true — 'beta' is optional

is.tuple([...], restGuard?)

Validates a fixed-length array where each position has its own guard. Pass a second argument to allow variadic trailing elements.
// Fixed length
const Point = is.tuple([is.number, is.number]);
Point([10, 20]);     // true
Point([10, 20, 30]); // false — too many elements

// With rest elements
const Args = is.tuple([is.string], is.number);
Args(['cmd']);            // true — rest is optional
Args(['cmd', 1, 2, 3]);  // true — [string, ...number[]]
Args(['cmd', 'nope']);    // false — rest element must be number

is.union(...), is.intersection(...), is.xor(...)

is.union(...guards) — passes if the value satisfies at least one guard.
const StringOrNumber = is.union(is.string, is.number, is.boolean);
StringOrNumber('hello'); // true — string | number | boolean
StringOrNumber(null);    // false
is.intersection(...guards) — passes if the value satisfies all guards.
const Named = is.object({ name: is.string });
const Aged  = is.object({ age: is.number });
const Person = is.intersection(Named, Aged);

Person({ name: 'Alice', age: 30 }); // true — { name: string } & { age: number }
Person({ name: 'Alice' });          // false
is.xor(...guards) — passes if the value satisfies exactly one guard.
const XorGuard = is.xor(
  is.object({ a: is.string }),
  is.object({ b: is.number }),
);

XorGuard({ a: 'hello' });           // true — matches first only
XorGuard({ a: 'hello', b: 1 });     // false — matches both

is.templateLiteral(...)

Validates that a string matches a template literal pattern. Accepts a mix of string segments and guards for interpolated positions.
const route = is.templateLiteral('/users/', is.number);
route('/users/42');    // true
route('/users/abc');   // false

const method = is.templateLiteral(is.literal('GET', 'POST'), '://', is.string);
method('GET://api.example.com'); // true
method('DELETE://api.example.com'); // false

Built-in type guards

is.date

Validates a Date instance.
HelperValidates
.before(date)Date is before the given date
.after(date)Date is after the given date
.startOf(unit)Transformer — truncates to start of 'year', 'month', 'day', etc.
const pastDate = is.date.before(new Date());
pastDate.parse(new Date('2020-01-01')); // Ok(Date)

const normalized = is.date.startOf('year');
normalized.parse(new Date('2025-06-15')); // Ok(2025-01-01T00:00:00.000Z)

is.regexp

Validates a RegExp instance. Optionally validates against a specific pattern.
is.regexp(/hello/); // true
is.regexp('hello'); // false

const specific = is.regexp(/^[a-z]+$/);
specific.parse(/^[a-z]+$/); // Ok(RegExp)

is.url

Validates a URL instance (not a string — use is.string.url for strings).
is.url(new URL('https://example.com')); // true
is.url('https://example.com');          // false

const toHref = is.url.transform(u => u.href);
toHref.parse(new URL('https://example.com')); // Ok('https://example.com/')

is.map(keyGuard?, valueGuard?)

Validates a Map instance with optional key and value guards.
is.map()(new Map());                                    // true
is.map(is.string, is.number)(new Map([['a', 1]]));      // true
is.map(is.string, is.number).nonEmpty(new Map([['a', 1]])); // true
is.map().size(2)(new Map([['a', 1], ['b', 2]]));        // true

is.set(valueGuard?)

Validates a Set instance with an optional value guard.
is.set()(new Set());                         // true
is.set(is.number)(new Set([1, 2, 3]));       // true
is.set(is.string).nonEmpty(new Set(['a']));  // true
is.set(is.number).subsetOf([1, 2, 3, 4])(new Set([1, 2])); // true

is.promise

Validates any thenable (has a .then method).
is.promise(Promise.resolve(42)); // true
is.promise(42);                  // false

is.error

Validates an Error instance.
HelperValidates
.message(str)Error message equals str
.name(str)Error name equals str
is.error(new Error('oops'));                    // true
is.error.message('oops')(new Error('oops'));    // true
is.error.name('TypeError')(new TypeError('bad')); // true

is.file

Validates a File or Blob instance.
HelperValidates
.type(mimeType)MIME type matches
.maxSize(bytes)File size ≤ bytes
const imageFile = is.file.type('image/png').maxSize(5 * 1024 * 1024);
imageFile.parse(uploadedFile); // Ok(File) or Err(...)

Custom and chas-specific guards

is.custom(fn)

Creates a guard from any predicate function. Use a TypeScript type predicate for full narrowing, or pass a generic type parameter.
const isOdd = is.custom((n): n is number => typeof n === 'number' && n % 2 !== 0);
isOdd(3); // true
isOdd(2); // false

const isEven = is.custom<number>(n => typeof n === 'number' && n % 2 === 0);
isEven(4); // true

is.result()

Guards a Result<T, E> value from the ts-chas result module.
import { ok, err } from 'ts-chas/result';

is.result()(ok(42));              // true
is.result(is.number)(ok(42));     // true
is.result().ok(is.number)(ok(42)); // true — narrows to Ok variant
is.result().err(is.string)(err('fail')); // true — narrows to Err variant

is.option()

Guards an Option<T> value.
import { some, none } from 'ts-chas/option';

is.option()(some(42));         // true
is.option(is.number)(some(42)); // true
is.option().some(is.number)(some(42)); // true
is.option().none(none());      // true

is.tagged(factory)

Guards tagged errors created with defineErrs.
import { defineErrs } from 'ts-chas/tagged-errs';

const AppError = defineErrs({
  NotFound: (id: string) => ({ id }),
  Forbidden: (reason: string) => ({ reason }),
});

is.tagged(AppError.NotFound)(error); // narrows to NotFoundErr — typed id available
is.tagged(AppError)(error);          // narrows to NotFoundErr | ForbiddenErr
is.tagged('NotFound')(error);        // structural match on _tag