(value: unknown) => value is T, so it narrows types in if blocks. Each property access or method call returns a new guard — nothing is mutated.
The is object
Import is from ts-chas/guard. It is the single entry point for all built-in guards.
is is itself a guard (or a factory that produces one). You chain helpers by accessing properties or calling methods directly on the guard:
How chaining works
Each step in a chain applies left to right. Transformers (like.trim()) mutate the value flowing through the chain, while validators (like .email) refine it.
Universal helpers
Every guard — regardless of type — exposes the following methods..parse(value)
Validates value and returns Result<T, GuardErr>. If the guard has a transform pipeline (e.g., .trim()), the transformed value is returned on success.
.assert(value)
Like .parse(), but throws a GuardErr on failure instead of returning an Err. Returns the typed value on success.
.error(msg) / .error(fn)
Overrides the default error message. Accepts a static string or a function receiving { meta, value }.
.nullable
Widens the guard to also accept null. Returns Guard<T | null>.
.optional
Widens the guard to also accept undefined. Returns Guard<T | undefined>.
.nullish
Widens the guard to also accept null or undefined. Returns Guard<T | null | undefined>.
.and(otherGuard)
Logical AND: both guards must pass. The value is typed as T & U.
.or(otherGuard)
Logical OR: either guard can pass. The value is typed as T | U. Type-specific helpers are dropped on the result since the type is now a union.
.where(predicate)
Adds a custom inline validation rule. The predicate receives the (possibly transformed) value.
.brand(tag)
Adds a compile-time brand to the output type. Has no runtime effect — use it to distinguish semantically different values of the same primitive type.
.fallback(value)
Sets a fallback value returned by .parse() and .assert() when validation fails, instead of producing an error. Does not affect the boolean type predicate.
.transform(fn)
Applies a type-changing transformation to the validated value. The guard still validates the original input; .parse() / .assert() return the transformed value. Drops type-specific helpers since the output type may differ.
.refine(fn)
Like .transform(), but the output type stays T and type-specific helpers are preserved.
.not
Inverts the guard. Passes when the original fails; typed as Guard<unknown>.
.array
Wraps the guard as an element guard for arrays. Equivalent to is.array(thisGuard).
Standard Schema (~standard)
Every guard implements the Standard Schema v1 specification via the ~standard property. This makes guards compatible with tRPC, react-hook-form, Drizzle, and any other library that consumes the spec — no adapter needed.
Extending the is namespace
Use is.extend({ ... }) to add custom guards to a new is instance. The base guards remain available on the returned object.
extend — it performs a shallow merge with baseIs.
Type utilities
InferGuard<T>
Extracts the validated type from a guard.
Guard<T, H>
The guard interface itself. T is the validated type; H is the type-specific helpers object.
GuardErr
The error type returned by .parse() on failure.