Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

guardz

thiennp1.2kMIT1.12.2TypeScript support: included

A simple and lightweight TypeScript type guard library for runtime type validation.

typescript, type-guard, typeguard, runtime-validation, runtime-type-checking, type-safety, schema-validation, data-validation, input-validation, api-validation, form-validation, error-handling, structured-errors, json-validation, object-validation, array-validation, union-types, intersection-types, composite-types, zero-dependencies, lightweight, bundle-size, performance, monitoring, debugging, testing, assertion, type-checking, type-inference, typesafe, react, angular, vue, nodejs, express, nextjs, nestjs, fastify, koa, webpack, vite, rollup, esbuild, swc, jest, vitest, cypress, playwright, axios, fetch, graphql, rest-api, microservices, serverless, aws, azure, gcp, docker, kubernetes, ci-cd, github-actions, gitlab-ci, vercel, netlify, deno, bun, esm, commonjs, umd, tree-shaking, code-splitting, bundle-optimization, developer-experience, dx, developer-tools, typescript-ecosystem, javascript-ecosystem, frontend, backend, fullstack, web-development, mobile-development, desktop-development, cli-tools, build-tools, compiler, transpiler, static-analysis, linting, code-quality, best-practices, enterprise, startup, open-source, mit-license

readme

Guardz

npm version License: MIT TypeScript Node.js npm downloads bundle size

A comprehensive TypeScript type guard library with advanced validation capabilities, error reporting, and performance optimizations.

🚀 Quick Start

Installation

# npm
npm install guardz

# yarn
yarn add guardz

# pnpm
pnpm add guardz

TypeScript Configuration

Ensure your tsconfig.json includes:

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "exactOptionalPropertyTypes": true
  }
}

Basic Usage

import { isNonEmptyString, isNumber, isString, isType } from 'guardz';

// Basic guard
const value: unknown = getUnknownValue();
if(isString(value)) {
  // TypeScript now knows value is a string - type narrowing in action
  console.log(value.length); // Safe to access string properties
}

// Simulate getting data from an external source (API, database, etc.)
const maybeUser: unknown = await getUserInfoFromServer();

// Define a type guard for user type checking
const isUser = isType<UserDTO>({
  id: isNumber,
  name: isNonEmptyString,
  email: isNonEmptyString,
});

// Use type guard for type narrowing
if (isUser(maybeUser)) {
  // TypeScript now knows maybeUser is a valid UserDTO
  console.log(maybeUser.id);
  console.log(maybeUser.name);
  console.log(maybeUser.email);
}

🎯 Type Guards vs Validators

Guardz is a type guard library, not a validation library.

Guardz focuses on providing lightweight, composable type guards that enable TypeScript's type narrowing while maintaining excellent performance. For a detailed explanation of the differences between type guards and validators, see this comprehensive guide.

✨ Features

  • Comprehensive Type Guards: 50+ built-in type guards for all JavaScript types
  • Advanced Type Narrowing: Array type guards, object type guards, union types, and more
  • TypeScript Integration: Seamless type narrowing with exact type inference
  • Performance Optimized: Fast type guards with minimal overhead
  • TypeScript First: Full type safety with precise type inference
  • Zero Dependencies: Lightweight with no external dependencies
  • Tree Shaking: Optimized for bundle size with tree shaking support

📖 Basic Examples

Basic Type Guards

import { isString, isNumber, isBoolean, isSymbol, isArrayWithEachItem, isObject } from 'guardz';

isString('hello');        // true
isNumber(42);             // true
isBoolean(true);          // true
isSymbol(Symbol('a'));    // true
isArrayWithEachItem(isNumber)([1, 2, 3]);     // true
isObject({ a: 1 });       // true

isSymbol Example

import { isSymbol } from 'guardz';

const value: unknown = Symbol('test');
if (isSymbol(value)) {
  // value is now typed as symbol
  console.log(value.toString());
}

Object Type Guards

import { isType, isString, isNumber, isPositiveInteger, isUndefinedOr } from 'guardz';

interface User {
  id: number;
  name: string;
  email: string;
  age?: number;
}

const isUser = isType<User>({
  id: isPositiveInteger,
  name: isString,
  email: isString,
  age: isUndefinedOr(isNumber), // Handle optional property
});

const user = { id: 1, name: 'John', email: 'john@example.com' };
console.log(isUser(user)); // true

Array Type Guards

import { isArrayWithEachItem, isString, isNumber } from 'guardz';

const isStringArray = isArrayWithEachItem(isString);
const isNumberArray = isArrayWithEachItem(isNumber);

console.log(isStringArray(['a', 'b', 'c'])); // true
console.log(isNumberArray([1, 2, 3])); // true

Array Utilities

import { isString, isNumber, isType, by } from 'guardz';

const isUser = isType({ name: isString, age: isNumber });

const users = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: '30' }, // invalid
  { name: 'Charlie', age: 35 },
];

// ❌ This won't work due to parameter mismatch
// const validUsers = users.filter(isUser);

// ✅ Use by for simple filtering
const validUsers = users.filter(by(isUser));
console.log('Valid users:', validUsers);

Union Types

import { isOneOfTypes, isString, isNumber, isBoolean } from 'guardz';

const isPrimitive = isOneOfTypes(isString, isNumber, isBoolean);

console.log(isPrimitive('hello')); // true
console.log(isPrimitive(42));      // true
console.log(isPrimitive(true));    // true
console.log(isPrimitive({}));      // false

Error Handling

import { isType, isString, isNumber } from 'guardz';

const errors: string[] = [];
const config = {
  identifier: 'user',
  callbackOnError: (error: string) => errors.push(error),
  errorMode: 'multi', // 'single' | 'multi' | 'json'
};

const isUser = isType({
  name: isString,
  age: isNumber,
});

const invalidUser = { name: 123, age: 'thirty' };
const result = isUser(invalidUser, config);

console.log(result); // false
console.log(errors); // ['user.name: Expected string, got number (123)', 'user.age: Expected number, got string ("thirty")']

Pattern Validation

import { isRegex, isPattern } from 'guardz';
import type { Pattern } from 'guardz';

// Validate RegExp objects
const patterns: unknown[] = [/^[a-z]+$/, new RegExp('\\d+'), 'not a regex'];
patterns.forEach(pattern => {
  if (isRegex(pattern)) {
    console.log(`Valid RegExp: ${pattern.source} (flags: ${pattern.flags})`);
  }
});

// Create branded types for pattern-matched strings
type Email = Pattern<'Email'>;
type PhoneNumber = Pattern<'PhoneNumber'>;
type URL = Pattern<'URL'>;

const isEmail = isPattern<'Email'>(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
const isPhoneNumber = isPattern<'PhoneNumber'>('^\\+?[\\d\\s\\-()]{10,}$');
const isUrl = isPattern<'URL'>('^https?:\\/\\/.+');

// Validate strings against patterns
const email: unknown = 'user@example.com';
if (isEmail(email)) {
  // email is now typed as Email (branded string)
  console.log(`Valid email: ${email}`);
}

const phone: unknown = '+1-555-123-4567';
if (isPhoneNumber(phone)) {
  // phone is now typed as PhoneNumber (branded string)
  console.log(`Valid phone: ${phone}`);
}

// Type safety with branded types
function processEmail(email: Email) {
  // This function only accepts validated email strings
  console.log(`Processing email: ${email}`);
}

function processPhoneNumber(phone: PhoneNumber) {
  // This function only accepts validated phone number strings
  console.log(`Processing phone: ${phone}`);
}

// These work with type safety:
const validEmail: unknown = 'user@example.com';
if (isEmail(validEmail)) {
  processEmail(validEmail); // TypeScript knows this is safe
}

// These would cause TypeScript errors:
// processEmail('invalid-email'); // Error: Argument of type 'string' is not assignable to parameter of type 'Email'
// processPhoneNumber('123'); // Error: Argument of type 'string' is not assignable to parameter of type 'PhoneNumber'

🎯 Common Use Cases

API Response Validation

import { isType, isString, isNumber, isArrayWithEachItem, isOneOf } from 'guardz';

interface ApiResponse<T> {
  data: T;
  status: 'success' | 'error';
  message: string;
  timestamp: number;
}

const isUserResponse = isType<ApiResponse<User>>({
  data: isType({
    id: isNumber,
    name: isString,
    email: isString,
  }),
  status: isOneOf('success', 'error'), // Use isOneOf for exact values
  message: isString,
  timestamp: isNumber,
});

// Validate API responses
const response = await fetch('/api/users/1');
const data = await response.json();

if (isUserResponse(data)) {
  console.log('Valid user:', data.data.name);
} else {
  console.log('Invalid response format');
}

Form Data Validation

import { isType, isString, isNumber, isPositiveInteger } from 'guardz';

interface RegistrationForm {
  username: string;
  email: string;
  age: number;
  password: string;
}

const isRegistrationForm = isType<RegistrationForm>({
  username: isString,
  email: isString, // Could add email regex validation
  age: isPositiveInteger,
  password: isString,
});

const formData = {
  username: 'john_doe',
  email: 'john@example.com',
  age: 25,
  password: 'secure123',
};

if (isRegistrationForm(formData)) {
  // Process valid form data
  await registerUser(formData);
} else {
  // Handle validation errors
  showValidationErrors(errors);
}

Database Result Validation

import { isType, isString, isNumber, isDate } from 'guardz';

interface DatabaseUser {
  id: number;
  username: string;
  email: string;
  created_at: string;
  updated_at: string;
}

const isDatabaseUser = isType<DatabaseUser>({
  id: isNumber,
  username: isString,
  email: isString,
  created_at: isString,
  updated_at: isString,
});

// Validate database results
const users = await db.query('SELECT * FROM users');
const validUsers = users.filter(isDatabaseUser);

Configuration Validation

import { isType, isString, isNumber, isBoolean } from 'guardz';

interface AppConfig {
  port: number;
  database: {
    host: string;
    port: number;
    name: string;
  };
  features: {
    auth: boolean;
    caching: boolean;
  };
}

const isAppConfig = isType<AppConfig>({
  port: isNumber,
  database: isType({
    host: isString,
    port: isNumber,
    name: isString,
  }),
  features: isType({
    auth: isBoolean,
    caching: isBoolean,
  }),
});

// Validate environment configuration
const config = {
  port: process.env.PORT ? parseInt(process.env.PORT) : 3000,
  database: {
    host: process.env.DB_HOST || 'localhost',
    port: process.env.DB_PORT ? parseInt(process.env.DB_PORT) : 5432,
    name: process.env.DB_NAME || 'myapp',
  },
  features: {
    auth: process.env.AUTH_ENABLED === 'true',
    caching: process.env.CACHE_ENABLED === 'true',
  },
};

if (!isAppConfig(config)) {
  throw new Error('Invalid configuration');
}

🔧 Advanced Features

Reusable Type Guard Patterns

Create reusable type guard functions for consistent validation patterns:

import { isString, isNumber, isPositiveInteger, isType } from 'guardz';

// Create semantic type guards using existing functions
const isUserId = isPositiveInteger; // Already a reusable type guard
const isEmail = isString; // Already a reusable type guard
const isName = isString; // Already a reusable type guard

// Use them consistently across your application
interface User {
  id: number;        // Uses isUserId (isPositiveInteger)
  name: string;      // Uses isName (isString)
  email: string;     // Uses isEmail (isString)
}

const isUser = isType<User>({
  id: isUserId,
  name: isName,
  email: isEmail,
});

Generic Types

For complex generic types with conditional properties, use factory functions with isType:

import { isType, isString, isNumber, isUndefinedOr } from 'guardz';

// Define generic types with conditional properties
type ApiKeysSelect<T extends boolean = true> = {
  name: T extends true ? string : string | undefined;
  collectionPermissions: T extends true ? string : string | undefined;
  updatedAt: T extends true ? string : string | undefined;
  createdAt: T extends true ? string : string | undefined;
  enableAPIKey: T extends true ? boolean : boolean | undefined;
  apiKey: T extends true ? string : string | undefined;
  apiKeyIndex: T extends true ? number : number | undefined;
};

// Create type guard factory for generic types
export const isApiKeysSelect = <T extends boolean = true>(
  typeGuardT: TypeGuardFn<T>,
): TypeGuardFn<ApiKeysSelect<T>> =>
  isType<ApiKeysSelect<T>>({
    name: isUndefinedOr(typeGuardT),
    collectionPermissions: isUndefinedOr(typeGuardT),
    updatedAt: isUndefinedOr(typeGuardT),
    createdAt: isUndefinedOr(typeGuardT),
    enableAPIKey: isUndefinedOr(typeGuardT),
    apiKey: isUndefinedOr(typeGuardT),
    apiKeyIndex: isUndefinedOr(typeGuardT),
  });

// Usage
const isRequiredApiKeys = isApiKeysSelect(isString);
const isOptionalApiKeys = isApiKeysSelect(isUndefinedOr(isString));

💡 Pro Tip: For complex generic type validation with multiple conditional properties, consider using guardz-generator which automatically generates type guards for generic types and handles conditional properties efficiently.

Advanced Generic Patterns

// Multiple generic parameters
type Container<T, U, V extends boolean = true> = {
  primary: T;
  secondary: U;
  metadata: V extends true ? { timestamp: number; version: string } : undefined;
};

// Factory for multiple generic parameters
export const isContainer = <T, U, V extends boolean = true>(
  primaryGuard: TypeGuardFn<T>,
  secondaryGuard: TypeGuardFn<U>,
  metadataGuard?: TypeGuardFn<{ timestamp: number; version: string }>,
): TypeGuardFn<Container<T, U, V>> =>
  isType<Container<T, U, V>>({
    primary: primaryGuard,
    secondary: secondaryGuard,
    metadata: metadataGuard ? isUndefinedOr(metadataGuard) : undefined,
  });

// Usage
const isStringNumberContainer = isContainer(isString, isNumber);
const isStringNumberContainerWithMetadata = isContainer(
  isString,
  isNumber,
  isType({ timestamp: isNumber, version: isString })
);

Performance Optimizations

import { isType, isString, isNumber, isArrayWithEachItem } from 'guardz';

// Optimized for repeated validation
const isUser = isType({
  id: isNumber,
  name: isString,
  tags: isArrayWithEachItem(isString),
});

// Reuse the same guard instance
const users = [/* large array of user objects */];
const validUsers = users.filter(isUser); // Fast validation

// Use appropriate error modes for performance
const fastConfig = { errorMode: 'single' }; // Fastest
const detailedConfig = { errorMode: 'multi' }; // More detailed
const treeConfig = { errorMode: 'json' }; // Most detailed

🔄 Migration Guide

From Zod

// Zod
import { z } from 'zod';
const UserSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string().email(),
});

// Guardz
import { isType, isNumber, isString } from 'guardz';
const isUser = isType({
  id: isNumber,
  name: isString,
  email: isString, // Add custom email validation if needed
});

From Joi

// Joi
import Joi from 'joi';
const userSchema = Joi.object({
  id: Joi.number().required(),
  name: Joi.string().required(),
  email: Joi.string().email().required(),
});

// Guardz
import { isType, isNumber, isString } from 'guardz';
const isUser = isType({
  id: isNumber,
  name: isString,
  email: isString,
});

From Yup

// Yup
import * as yup from 'yup';
const userSchema = yup.object({
  id: yup.number().required(),
  name: yup.string().required(),
  email: yup.string().email().required(),
});

// Guardz
import { isType, isNumber, isString } from 'guardz';
const isUser = isType({
  id: isNumber,
  name: isString,
  email: isString,
});

🛠️ Troubleshooting

Common Issues

TypeScript Errors

Problem: Type 'unknown' is not assignable to parameter of type 'TypeGuardFn<T>'

Solution: Ensure you're using the correct type guard function:

// ❌ Wrong
const isUser = isType({
  id: isNumber, // This is correct
  name: 'string', // ❌ This is wrong - should be isString
});

// ✅ Correct
const isUser = isType({
  id: isNumber,
  name: isString, // ✅ Use the type guard function
});

Performance Issues

Problem: Validation is slow with large objects

Solution: Use appropriate error modes and optimize validation:

// ❌ Slow - collects all errors
const result = isUser(data, { errorMode: 'multi' });

// ✅ Fast - stops at first error
const result = isUser(data, { errorMode: 'single' });

// ✅ Fastest - no error collection
const result = isUser(data);

Bundle Size Issues

Problem: Large bundle size

Solution: Use tree shaking and import only what you need:

// ❌ Imports everything
import * as guardz from 'guardz';

// ✅ Only imports what you need
import { isType, isString, isNumber } from 'guardz';

Debugging

Enable detailed error reporting:

const errors: string[] = [];
const config = {
  identifier: 'user',
  callbackOnError: (error: string) => {
    errors.push(error);
    console.log('Validation error:', error);
  },
  errorMode: 'multi',
};

const result = isUser(data, config);
console.log('All errors:', errors);

⚡ Performance Tips

Error Mode Selection

  • single (default): Fastest, stops at first error
  • multi: Medium speed, collects all errors with details
  • json: Slowest, provides hierarchical error tree structure

Validation Strategies

// For production - fast validation
const isUserFast = isType({
  id: isNumber,
  name: isString,
  email: isString,
});

// For development - detailed errors
const isUserDev = isType({
  id: isNumber,
  name: isString,
  email: isString,
});

// Usage
const config = process.env.NODE_ENV === 'production' 
  ? undefined 
  : { errorMode: 'multi', callbackOnError: console.error };

Caching Type Guards

// Create type guards once, reuse them
const isUser = isType({
  id: isNumber,
  name: isString,
  email: isString,
});

// Reuse the same guard instance
const validateUsers = (users: unknown[]) => {
  return users.filter(isUser);
};

🔧 API Reference

Primitive Type Guards

  • isString - Validates that a value is a string
  • isNumber - Validates that a value is a valid number (excludes NaN)
  • isBoolean - Validates that a value is a boolean
  • isBigInt - Validates that a value is a BigInt
  • isFunction - Validates that a value is a function (including regular functions, arrow functions, class constructors, and methods)
  • isSymbol - Validates that a value is a Symbol

Special Type Guards

  • isAsserted - Always returns true and asserts value is T (useful for 3rd party types without runtime validation)
  • isEnum - Creates a type guard that checks if a value matches any value from an enum
  • isEqualTo - Creates a type guard that checks if a value is exactly equal to a specific value using strict equality (===)
  • isRegex - Validates that a value is a RegExp object
  • isPattern<P> - Creates a type guard that validates strings against a regex pattern and returns a branded type

Array Type Guards

  • isArrayWithEachItem<T>(typeGuard: TypeGuardFn<T>) - Creates a type guard that validates arrays where each item matches a specific type
  • isNonEmptyArray - Validates that a value is a non-empty array
  • isNonEmptyArrayWithEachItem<T>(typeGuard: TypeGuardFn<T>) - Creates a type guard that validates non-empty arrays where each item matches a specific type

Object Type Guards

  • isNonNullObject - Validates that a value is a non-null object (excludes arrays)
  • isType<T>(schema: Record<string, TypeGuardFn<any>>) - Creates a type guard that validates objects against a schema
  • isObject<T>(schema: Record<string, TypeGuardFn<any>>) - Alias for isType - creates a type guard for a specific object shape
  • isObjectWith<T>(schema: Record<string, TypeGuardFn<any>>) - Alias for isType - validates objects with specific properties
  • isObjectWithEachItem<T>(typeGuard: TypeGuardFn<T>) - Creates a type guard that validates plain objects where each property value matches a specific type (only checks enumerable own properties)

Number Type Guards

  • isInteger - Validates that a value is an integer (whole number)
  • isPositiveInteger - Validates that a value is a positive integer (greater than 0 and a whole number)
  • isNegativeInteger - Validates that a value is a negative integer (less than 0 and a whole number)
  • isNonNegativeInteger - Validates that a value is a non-negative integer (0 or greater and a whole number)
  • isNonPositiveInteger - Validates that a value is a non-positive integer (0 or less and a whole number)
  • isPositiveNumber - Validates that a value is a positive number (greater than 0)
  • isNegativeNumber - Validates that a value is a negative number (less than 0)
  • isNonNegativeNumber - Validates that a value is a non-negative number (0 or greater)
  • isNonPositiveNumber - Validates that a value is a non-positive number (0 or less)
  • isNumeric - Validates that a value is numeric (a number or a string that can be converted to a number)
  • isDateLike - Validates that a value can be treated as a Date (Date object, date string, or numeric timestamp)

String Type Guards

  • isNonEmptyString - Validates that a value is a non-empty string (trims whitespace, so strings containing only whitespace are considered empty)

Null/Undefined Type Guards

  • isNil - Validates that a value is null or undefined
  • isNullOr - Creates a type guard that validates if a value is either null or matches a specific type
  • isUndefinedOr - Creates a type guard that validates if a value is either undefined or matches a specific type
  • isNilOr - Creates a type guard that validates if a value is either of type T, null, or undefined

Union Type Guards

  • isOneOf - Creates a type guard that checks if a value matches one of several specific values using strict equality (===)
  • isOneOfTypes - Creates a type guard that checks if a value matches at least one of several type guards

Web API Type Guards

  • isDate - Validates that a value is a valid Date object (excludes invalid dates like new Date("invalid"))
  • isError - Validates that a value is an Error object
  • isBlob - Validates that a value is a Blob object
  • isFile - Validates that a value is a File object
  • isFileList - Validates that a value is a FileList object
  • isFormData - Validates that a value is a FormData object
  • isURL - Validates that a value is a URL object
  • isURLSearchParams - Validates that a value is a URLSearchParams object

Collection Type Guards

  • isMap - Validates that a value is a Map object
  • isSet - Validates that a value is a Set object
  • isIndexSignature - Creates a type guard that validates objects with index signatures (objects with dynamic keys of a specific type and values of a specific type)

Utility Type Guards

  • isUnknown - Always returns true (useful for unknown types)
  • isAny - Always returns true (useful for any types)
  • isDefined - Validates that a value is defined (not null/undefined)
  • isBooleanLike - Validates that a value can be treated as a boolean (boolean, "true"/"false", "1"/"0", or 1/0)
  • isExtensionOf - Creates a type guard for types that extend a base type by combining a base type guard with validation for additional properties (useful for inheritance patterns)
  • isIntersectionOf - Creates a type guard that validates a value against multiple type guards, ensuring the value satisfies all of them
  • isPartialOf - Creates a type guard that validates partial objects matching a specific type (allows missing properties)
  • isTuple - Creates a type guard that validates tuples (fixed-length arrays with specific types at each position)

Schema Type Guards

  • isSchema - Creates a type guard function for object schemas with improved nested type support (automatically handles nested structures)
  • isShape - Alias for isSchema
  • isNestedType - Alias for isSchema

Advanced Type Guards

  • isBranded - Creates a type guard function for a branded type using a predicate function (validates and narrows to branded types)
  • guardWithTolerance - Validates data against a type guard but returns the data regardless of validation result (useful for logging errors while proceeding with potentially invalid data)

Type Guard Error Generation

  • generateTypeGuardError - Generates error messages for type guard failures

Utility Types

  • PredicateFn - A predicate function that validates a value and returns true if valid, false otherwise

Type Converters

  • toNumber - Converts a Numeric value to a number (safely converts validated numeric values)
  • toDate - Converts a DateLike value to a Date object (safely converts validated date values)
  • toBoolean - Converts a BooleanLike value to a boolean (safely converts validated boolean values)

Validation Types

  • ValidationError - Error type for validation failures with path, expected type, actual value, and message
  • ValidationTree - Tree structure for hierarchical validation errors
  • ValidationResult - Result type for validation operations with validity status and errors
  • ValidationContext - Context type for validation operations with path and configuration

Branded Types

  • Branded<T, B> - Branded type with a specific brand identifier (supports string and unique symbol brands)
  • BrandSymbols - Predefined brand symbols for common use cases
  • BrandedWith<T, K> - Utility type to create branded types with predefined symbols
  • NonEmptyArray<T> - Array type that cannot be empty
  • NonEmptyString - String type that cannot be empty
  • PositiveNumber - Number type that must be positive
  • NegativeNumber - Number type that must be negative
  • NonNegativeNumber - Number type that must be non-negative
  • NonPositiveNumber - Number type that must be non-positive
  • PositiveInteger - Integer type that must be positive
  • NegativeInteger - Integer type that must be negative
  • NonNegativeInteger - Integer type that must be non-negative
  • NonPositiveInteger - Integer type that must be non-positive
  • Integer - Integer type
  • Nullable<T> - Type that can be null
  • Numeric - Numeric type (number or string that can be converted to number)
  • DateLike - Date-like type (Date object, date string, or numeric timestamp)
  • BooleanLike - Boolean-like type (boolean, "true"/"false", "1"/"0", or 1/0)
  • Pattern<P> - Branded string type that matches a specific regex pattern

🛠️ Error Generation

Guardz provides detailed error reporting with configurable error handling:

import { isType, isString, isNumber } from 'guardz';

const errors: string[] = [];
const config = {
  identifier: 'user',
  callbackOnError: (error: string) => errors.push(error),
  errorMode: 'multi', // 'single' | 'multi' | 'json'
};

const isUser = isType({
  name: isString,
  age: isNumber,
});

const invalidUser = { name: 123, age: 'thirty' };
const result = isUser(invalidUser, config);

console.log(errors);
// [
//   'user.name: Expected string, got number (123)',
//   'user.age: Expected number, got string ("thirty")'
// ]

Error Modes

  • single - Basic error messages (default)
  • multi - Detailed error messages with values
  • json - Hierarchical error tree structure

🎯 Utility Types

Guardz provides utility types for enhanced type safety:

import type { TypeGuardFn, TypeGuardFnConfig } from 'guardz';

// TypeGuardFn<T> - Type guard function type
// TypeGuardFnConfig - Configuration for type guards

🔐 Unique Symbol Branded Types

Guardz supports branded types with unique symbols for enhanced type safety:

import { isBranded, Branded, BrandSymbols, type BrandedWith } from 'guardz';

// Custom unique symbol brands
const UserIdBrand = Symbol('UserId');
type UserId = Branded<number, typeof UserIdBrand>;

const isUserId = isBranded<UserId>((value) => {
  return typeof value === 'number' && value > 0 && Number.isInteger(value);
});

// Predefined brand symbols
type Email = BrandedWith<string, 'Email'>;
const isEmail = isBranded<Email>((value) => {
  if (typeof value !== 'string') return false;
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(value);
});

// Usage
const id: unknown = 123;
if (isUserId(id)) {
  // id is now typed as UserId (number & { readonly brand: typeof UserIdBrand })
  console.log(id);
}

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

git clone https://github.com/thiennp/guardz.git
cd guardz
npm install
npm test

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

📚 Documentation

🆘 Support

🙏 Acknowledgments

Thanks to all contributors and the TypeScript community for making this project possible.


Made with ❤️ by the Guardz Team

changelog

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[1.12.1] - 2024-12-20

✨ New Features

  • isSymbol: Type guard for symbol and unique symbol values

[1.12.0] - 2024-12-20

✨ New Features

  • by Function: New array utility to solve parameter mismatch between type guards and array methods
  • Array Method Compatibility: Type guards now work directly with filter, find, findIndex, some, every, map
  • Simplified API: Clean syntax with users.filter(by(isUser)) instead of complex workarounds
  • Type Safety: Full TypeScript support with proper type narrowing for array methods
  • Unique Symbol Branded Types: Enhanced branded type support with unique symbols
  • Predefined Brand Symbols: Common brand symbols for easy branded type creation
  • BrandedWith Utility: Type utility for creating branded types with predefined symbols

🔧 Array Utilities

  • Parameter Mismatch Solution: Handles (value, config) vs (value, index, array) mismatch
  • Universal Compatibility: Works with all array methods and type guards
  • Minimal Overhead: Simple parameter conversion with no performance impact
  • Intuitive Usage: Natural reading flow - "filter by isUser"

📚 Documentation & Examples

  • Array Utilities Section: Added comprehensive documentation in README
  • Complete Examples: Added examples/array-utilities.ts with full usage demonstrations
  • Integration Examples: Shows usage with all array methods and complex type guards
  • Best Practices: Clear guidance on when to use by vs isArrayWithEachItem

🔐 Branded Type Enhancements

  • Unique Symbol Support: Branded types now support both string and unique symbol brands
  • Type Safety: Better type safety with unique symbols preventing string literal conflicts
  • Predefined Symbols: Common brand symbols for UserId, Email, Password, Age, etc.
  • Backward Compatibility: Existing string-based branded types continue to work
  • Enhanced Examples: Comprehensive examples showing both approaches

🧪 Testing

  • Comprehensive Tests: 8 tests covering all array utility functionality
  • All Tests Passing: 1077 tests across 71 test suites
  • Clean Build: TypeScript compilation successful
  • No Breaking Changes: 100% backward compatible

[1.11.8] - 2024-12-20

📚 Documentation Enhancements

  • Comprehensive Showcases: Added complete TypeScript type guard examples covering all possible cases
  • Real-World Scenarios: Added practical examples for API responses, form validation, configuration
  • Advanced Patterns: Added examples for conditional validation, recursive types, index signatures
  • Error Handling: Added detailed examples for multiple error modes and reporting
  • Performance Optimizations: Added caching strategies and lazy validation examples
  • Documentation Structure: Created docs/README.md as navigation index
  • Updated Main README: Added documentation section with links to showcases and examples

🎯 Showcases Coverage

  • Primitive Types: String, number, boolean, BigInt with specializations
  • Object Types: Complex objects, nested structures, optional properties
  • Array Types: Arrays with specific item types, tuples, non-empty arrays
  • Union/Intersection: Complex type combinations and narrowing
  • Generic Types: Reusable type guards with constraints
  • Branded Types: Type-safe domain-specific types
  • Web APIs: Browser-specific type validation
  • Error Handling: Multiple error modes with detailed examples
  • Performance: Optimization strategies and best practices

🧪 Testing

  • All Tests Passing: 1026 tests across 68 test suites
  • Clean Build: TypeScript compilation successful
  • No Breaking Changes: 100% backward compatible

[1.11.7] - 2024-12-20

📚 Documentation Enhancements

  • Complete API Reference: Added all missing functions and types to documentation
  • Precise Descriptions: Replaced generic "Checks if" with specific action verbs
  • Correct Groupings: Moved functions to appropriate sections (e.g., isBooleanLike to Utility Type Guards)
  • Fixed Placeholder Information: Updated all repository URLs and links to correct values
  • Added Missing Sections: Type Converters, Validation Types, Branded Types
  • Enhanced Descriptions: More detailed explanations of function behavior and use cases

🧹 Documentation Cleanup

  • Removed Duplicates: Fixed duplicate entries in API reference
  • Corrected Groupings: Properly organized functions by their actual purpose
  • Fixed Links: All GitHub links now point to correct repositories
  • Updated References: All placeholder information replaced with actual values

🔧 Technical Improvements

  • Better Organization: Functions grouped by their actual behavior and purpose
  • Consistent Language: Standardized description format across all functions
  • Complete Coverage: All exported functions and types now documented
  • Professional Standards: Documentation now matches industry best practices

🧪 Testing

  • All Tests Passing: 1026 tests across 68 test suites
  • Clean Build: TypeScript compilation successful
  • No Breaking Changes: 100% backward compatible

[1.11.6] - 2024-12-20

📚 Documentation Enhancements

  • Professional README: Transformed to match top-tier package standards (React, Angular, TypeScript)
  • Comprehensive Installation Guide: Added npm, yarn, pnpm installation options
  • TypeScript Configuration: Added required TypeScript settings
  • Common Use Cases: Added API response, form data, database, and configuration validation examples
  • Migration Guide: Added migration paths from Zod, Joi, Yup
  • Troubleshooting Section: Added common issues and solutions
  • Performance Tips: Added optimization strategies and error mode selection
  • Advanced Generic Patterns: Enhanced generic types section with multiple parameter examples
  • guardz-generator Integration: Added recommendations for complex generic type handling

🧹 Project Cleanup

  • Removed isGeneric: Eliminated all isGeneric related files and functionality
  • Clean Architecture: Simplified project structure
  • Updated Examples: Removed references to deleted files
  • Consistent Versioning: Updated all version references to 1.11.6

🔧 Technical Improvements

  • Enhanced Error Handling: Better error reporting examples
  • Performance Optimization: Added caching strategies and error mode guidance
  • Type Safety: Improved generic type examples with exact type inference
  • Professional Standards: README now matches industry best practices

🧪 Testing

  • All Tests Passing: 1026 tests across 68 test suites
  • Clean Build: TypeScript compilation successful
  • No Breaking Changes: 100% backward compatible

[1.11.0] - 2024-12-20

✨ New Features

  • isIndexSignature: New type guard for validating objects with dynamic keys (index signatures)
  • isNumeric: New type guard for validating numeric values (numbers and string numbers)
  • isBooleanLike: New type guard for validating boolean-like values (boolean, "true"/"false", 1/0)
  • isDateLike: New type guard for validating date-like values (Date objects, date strings, timestamps)

🔧 Improvements

  • Enhanced Object Validation: Support for objects with both fixed properties and dynamic keys using isIntersectionOf
  • Flexible Type Validation: New utilities handle common real-world scenarios where data comes in various formats
  • Better Form Validation: Support for form inputs that return strings for boolean/numeric values
  • API Response Validation: Enhanced validation for API responses with mixed data types

📚 Documentation

  • Comprehensive Examples: Added examples/index-signature-usage.ts with practical usage patterns
  • Updated README: Added new utilities to the documentation
  • Real-world Use Cases: Examples for form validation, API responses, and configuration files

🧪 Testing

  • Comprehensive Test Coverage: 48 new tests for the new utilities
  • Integration Tests: Verified compatibility with existing composite type guards
  • Real-world Scenarios: Tests covering form validation, API responses, and configuration validation

🔄 Backward Compatibility

  • 100% Compatible: All existing code patterns work exactly the same
  • No Breaking Changes: All new utilities are additive
  • Type Safety: Enhanced TypeScript integration with proper type narrowing

[1.10.0] - 2024-12-19

🚀 Performance Optimizations

  • Duplicate Check Elimination: Eliminated redundant validation calls by implementing "pass value through function" approach
  • Unified Validation Logic: Single validation path for all error modes (single, multi, json)
  • Consistent Error Handling: Same error creation logic across all validation modes
  • 50% Reduction: In validation calls for complex union types (isOneOfTypes)

🔧 Internal Improvements

  • Optimized isOneOfTypes: Values are now validated only once, results are reused for error reporting
  • Optimized validateObject: Single error mode now uses unified validateProperty function
  • Optimized validateProperty: Unified validation function eliminates duplicate error creation logic
  • Functional Programming: Replaced imperative loops with functional constructs (for...of instead of for...let)

🔄 Backward Compatibility

  • 100% Compatible: All existing code patterns work exactly the same
  • Optional Config Parameters: Maintained config?: TypeGuardFnConfig | null signature
  • Error Behavior: Default single error mode behavior unchanged
  • Type Narrowing: TypeScript integration preserved
  • API Signature: No breaking changes to any public APIs

📚 Documentation

  • Updated README: Added performance optimization section
  • New Examples: Created performance optimization and backward compatibility examples
  • Enhanced Documentation: Better explanation of error modes and performance considerations

🧪 Testing

  • Comprehensive Tests: 609 tests passing across 55 test suites
  • Backward Compatibility Tests: Verified all existing patterns work correctly
  • Performance Tests: Validated optimization improvements

📦 Build

  • Clean Build: TypeScript compilation successful
  • Type Definitions: All .d.ts files generated correctly
  • No Dependencies: Remains dependency-free

[1.9.0] - 2024-12-18

✨ New Features

  • Multiple Error Modes: Added 'single', 'multi', and 'json' error reporting modes
  • JSON Tree Error Format: Structured error reporting with hierarchical validation information
  • Enhanced Error Messages: More detailed and actionable error feedback
  • Functional Programming: Pure functions with Higher-Order Functions (HoF) patterns

🔧 Improvements

  • Modular Architecture: Separated validation utilities into individual files
  • Better Error Handling: Consistent error creation and reporting
  • Type Safety: Enhanced TypeScript integration
  • Performance: Optimized error collection and reporting

📚 Documentation

  • Comprehensive Examples: Multiple error modes and JSON tree format
  • API Documentation: Detailed function descriptions and usage patterns
  • Error Message Guide: Clear explanation of error formats and modes

[1.8.0] - 2024-12-17

✨ New Features

  • Error Reporting: Added configurable error callback system
  • Detailed Error Messages: Field-specific error information
  • Custom Error Handling: Integration with logging and monitoring systems

🔧 Improvements

  • Better Type Guards: Enhanced validation logic
  • Error Context: Improved error message formatting
  • Performance: Optimized validation performance

[1.7.0] - 2024-12-16

✨ New Features

  • Composite Type Guards: Added isIntersectionOf and isExtensionOf
  • Union Type Guards: Added isOneOf and isOneOfTypes
  • Array Type Guards: Enhanced array validation capabilities

🔧 Improvements

  • Type Safety: Better TypeScript integration
  • Performance: Optimized validation logic
  • Documentation: Enhanced examples and guides

[1.6.0] - 2024-12-15

✨ New Features

  • Object Type Guards: Added isObject, isObjectWith, isNonNullObject
  • Array Type Guards: Added isArrayWithEachItem, isNonEmptyArray
  • Number Type Guards: Added various number validation functions

🔧 Improvements

  • Core Functionality: Enhanced isType function
  • Type Definitions: Better TypeScript support
  • Error Handling: Improved validation feedback

[1.5.0] - 2024-12-14

✨ New Features

  • Primitive Type Guards: Added isString, isNumber, isBoolean
  • Special Type Guards: Added isDate, isFunction, isError
  • Web API Guards: Added isFile, isBlob, isFormData

🔧 Improvements

  • Core Architecture: Established foundation for type guard system
  • Type Safety: Basic TypeScript integration
  • Documentation: Initial documentation and examples

[1.0.0] - 2024-12-13

🎉 Initial Release

  • Core Type Guard System: Basic isType function
  • TypeScript Integration: Type narrowing and type safety
  • Basic Documentation: README and examples
  • MIT License: Open source release

Migration Guide

Upgrading to v1.10.0

No migration required! Guardz v1.10.0 is 100% backward compatible with all previous versions.

// Existing code works exactly the same
const isUser = isType<User>({
  id: isNumber,
  name: isString,
  isActive: isBoolean
});

// Same validation behavior
const isValid = isUser(data);

// Same error reporting
isUser(data, {
  identifier: 'user',
  callbackOnError: (error) => console.log(error)
});

Optional: Use New Performance Optimizations

The performance optimizations are transparent to users, but you can benefit from them immediately:

// Union types are now optimized automatically
const isPrimitive = isOneOfTypes<string | number | boolean>(isString, isNumber, isBoolean);

// Complex validations use unified logic
const isComplexUser = isType<ComplexUser>({
  id: isNumber,
  name: isString,
  profile: isProfile,
  settings: isSettings,
  tags: isArrayWithEachItem(isString)
});

Upgrading to v1.9.0

No migration required! All existing code patterns work identically.

Upgrading to v1.8.0

No migration required! Error reporting is opt-in and doesn't affect existing code.


Support

For questions, issues, or contributions, please visit: