Guard your runtime. Harden your types.
Blazing-fast, tree-shakeable utilities for bridging TypeScriptβs compile-time safety with real-world runtime guarantees. Type guards, assertions, Result/Option monads, data pipelines, and environment validation β all in one lightweight, zero-dependency package.
Getting Started Β· API Reference Β· Why Guarden? Β· Contributing
- π 60+ type guards with automatic TypeScript narrowing
- β‘ Zero dependencies β nothing to audit, nothing to break
- π³ Tree-shakeable β import only what you use
- π¦ Dual ESM/CJS β works everywhere
- π§ͺ 313 tests with 100% coverage (statements, branches, functions, lines)
- π― TypeScript-first β written in TypeScript, for TypeScript
- ποΈ 5 modules β Guards, Assert, Result/Option, Transform, Env
npm install guarden
yarn add guarden
pnpm add guardenimport {
isString, isNumber, shape, // Guards
assert, invariant, // Assertions
Ok, Err, type Result, // Result monad
pipe, slugify, escapeHtml, // Transform
createEnv, envString, envNumber // Env validation
} from 'guarden';
// π‘οΈ Type Guards β automatic narrowing
const input: unknown = getApiResponse();
if (isString(input)) {
input.toUpperCase(); // β
TypeScript knows it's a string
}
// ποΈ Object Shape Validation
const isUser = shape({ name: isString, age: isNumber });
if (isUser(data)) {
console.log(data.name); // β
Fully typed
}
// β‘ Result Monad β no more try/catch
function divide(a: number, b: number): Result<number, string> {
if (b === 0) return Err('Division by zero');
return Ok(a / b);
}
divide(10, 2).match({
ok: (value) => console.log(`Result: ${value}`),
err: (error) => console.error(`Error: ${error}`),
});
// π Data Pipelines
const slug = pipe(' Hello, World! π ', (s) => s.trim(), slugify);
// β "hello-world"import { isString, shape, arrayOf } from 'guarden/guards';
import { assert, invariant } from 'guarden/assert';
import { Ok, Err, Some, None } from 'guarden/result';
import { pipe, slugify, escapeHtml } from 'guarden/transform';
import { createEnv, envString } from 'guarden/env';// Primitives
isString(v) | isNumber(v) | isBoolean(v) | isNull(v) | isUndefined(v)
isNullish(v) | isNonNullish(v) | isFunction(v) | isPrimitive(v)
// Structures
isArray(v) | isObject(v) | isPlainObject(v) | isDate(v) | isValidDate(v)
isMap(v) | isSet(v) | isRegExp(v) | isError(v) | isPromise(v)
// Advanced
isEmail(v) | isURL(v) | isUUID(v) | isISO8601(v) | isHexColor(v)
isPositiveNumber(v) | isInteger(v) | isNonEmptyArray(v)
// Factories
isInRange(0, 100)(v) | isOneOf(['a','b'] as const)(v)
isMinLength(3)(v) | isInstanceOf(TypeError)(v)
// Combinators
const guard = and(isInteger, isPositiveNumber);
const isUser = shape({ name: isString, age: isNumber });
const isStringArray = arrayOf(isString);assert(condition, 'msg');
assertDefined(value); // narrows away undefined
assertNonNull(value); // narrows away null | undefined
assertType(value, isString);
invariant(items.length > 0, 'bug!');
unreachable(dir); // exhaustive switch checkingconst result = Ok(42);
result.map(v => v * 2);
result.unwrapOr(0);
result.match({ ok: v => v, err: e => e });
const parsed = ResultUtils.from(() => JSON.parse(input));
const data = await ResultAsync.from(fetch('/api')).map(r => r.json()).unwrapOr(null);
const all = ResultUtils.all([Ok(1), Ok(2)]); // Ok([1, 2])pipe(' Hello World ', trim, lowercase, slugify); // "hello-world"
const processTitle = flow(trim, capitalize, (s) => truncate(s, 50));
toNumber('42') // Ok(42)
escapeHtml('<script>') // "<script>"
camelCase('hello world') // "helloWorld"
slugify('Hello! π') // "hello"export const env = createEnv({
DATABASE_URL: envString().url().required(),
PORT: envNumber().port().default(3000),
DEBUG: envBoolean().default(false),
NODE_ENV: envEnum(['development', 'production', 'test'] as const),
});
env.DATABASE_URL // string
env.PORT // number
env.DEBUG // boolean| Feature | Guarden | Zod | neverthrow | ts-pattern |
|---|---|---|---|---|
| Type Guards | β 60+ | β | β | β |
| Assertions | β | β | β | β |
| Result/Option | β | β | β | β |
| Data Transform | β | β (parse) | β | β |
| Env Validation | β | πΆ (manual) | β | β |
| Zero Dependencies | β | β | β | β |
| Bundle Size | ~3KB | ~14KB | ~5KB | ~3KB |
- Node.js >= 18.0.0
- TypeScript >= 5.0
MIT Β© Avinashvelu03
βββββββββββββββββββββββββββββββββββββββββββββββββ
β βββ βββ βββ β β βββββ ββββ βββ β
β βββββ βββββ βββββββββ βββββββ ββββββ βββ β
β βββ βββ βββ βββ βββ βββ βββ βββ β
β βββββ βββββ βββββββββ βββ βββ ββββββ βββ β
β βββ βββ βββ βββ βββ βββ βββ βββ β
β βββββββ βββ βββ βββ βββ βββββββ βββ βββ β
βββββββββββββββββββββββββββββββββββββββββββββββββ
Guarden guards your runtime for free. A star, a sponsor, or a share keeps it alive and growing.
Free ways to support:
- β Star on GitHub
- π File issues or feature requests
- π£οΈ Recommend Guarden to TypeScript devs who care about runtime safety
Built with β€οΈ by Avinash Velu