
Research
Two Malicious Rust Crates Impersonate Popular Logger to Steal Wallet Keys
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
A simple and lightweight TypeScript type guard library for runtime type validation.
A comprehensive TypeScript type guard library with advanced validation capabilities, error reporting, and performance optimizations.
# npm
npm install guardz
# yarn
yarn add guardz
# pnpm
pnpm add guardz
Ensure your tsconfig.json
includes:
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"exactOptionalPropertyTypes": true
}
}
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);
}
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.
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
import { isSymbol } from 'guardz';
const value: unknown = Symbol('test');
if (isSymbol(value)) {
// value is now typed as symbol
console.log(value.toString());
}
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
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
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);
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
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")']
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'
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');
}
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);
}
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);
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');
}
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,
});
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.
// 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 })
);
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
// 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
});
// 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,
});
// 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,
});
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
});
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);
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';
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);
single
(default): Fastest, stops at first errormulti
: Medium speed, collects all errors with detailsjson
: Slowest, provides hierarchical error tree structure// 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 };
// 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);
};
isString
- Validates that a value is a stringisNumber
- Validates that a value is a valid number (excludes NaN)isBoolean
- Validates that a value is a booleanisBigInt
- Validates that a value is a BigIntisFunction
- Validates that a value is a function (including regular functions, arrow functions, class constructors, and methods)isSymbol
- Validates that a value is a SymbolisAsserted
- 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 enumisEqualTo
- 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 objectisPattern<P>
- Creates a type guard that validates strings against a regex pattern and returns a branded typeisArrayWithEachItem<T>(typeGuard: TypeGuardFn<T>)
- Creates a type guard that validates arrays where each item matches a specific typeisNonEmptyArray
- Validates that a value is a non-empty arrayisNonEmptyArrayWithEachItem<T>(typeGuard: TypeGuardFn<T>)
- Creates a type guard that validates non-empty arrays where each item matches a specific typeisNonNullObject
- 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 schemaisObject<T>(schema: Record<string, TypeGuardFn<any>>)
- Alias for isType - creates a type guard for a specific object shapeisObjectWith<T>(schema: Record<string, TypeGuardFn<any>>)
- Alias for isType - validates objects with specific propertiesisObjectWithEachItem<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)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)isNonEmptyString
- Validates that a value is a non-empty string (trims whitespace, so strings containing only whitespace are considered empty)isNil
- Validates that a value is null or undefinedisNullOr
- Creates a type guard that validates if a value is either null or matches a specific typeisUndefinedOr
- Creates a type guard that validates if a value is either undefined or matches a specific typeisNilOr
- Creates a type guard that validates if a value is either of type T, null, or undefinedisOneOf
- 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 guardsisDate
- Validates that a value is a valid Date object (excludes invalid dates like new Date("invalid")
)isError
- Validates that a value is an Error objectisBlob
- Validates that a value is a Blob objectisFile
- Validates that a value is a File objectisFileList
- Validates that a value is a FileList objectisFormData
- Validates that a value is a FormData objectisURL
- Validates that a value is a URL objectisURLSearchParams
- Validates that a value is a URLSearchParams objectisMap
- Validates that a value is a Map objectisSet
- Validates that a value is a Set objectisIndexSignature
- Creates a type guard that validates objects with index signatures (objects with dynamic keys of a specific type and values of a specific type)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 themisPartialOf
- 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)isSchema
- Creates a type guard function for object schemas with improved nested type support (automatically handles nested structures)isShape
- Alias for isSchemaisNestedType
- Alias for isSchemaisBranded
- 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)generateTypeGuardError
- Generates error messages for type guard failuresPredicateFn
- A predicate function that validates a value and returns true if valid, false otherwisetoNumber
- 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)ValidationError
- Error type for validation failures with path, expected type, actual value, and messageValidationTree
- Tree structure for hierarchical validation errorsValidationResult
- Result type for validation operations with validity status and errorsValidationContext
- Context type for validation operations with path and configurationBranded<T, B>
- Branded type with a specific brand identifier (supports string and unique symbol brands)BrandSymbols
- Predefined brand symbols for common use casesBrandedWith<T, K>
- Utility type to create branded types with predefined symbolsNonEmptyArray<T>
- Array type that cannot be emptyNonEmptyString
- String type that cannot be emptyPositiveNumber
- Number type that must be positiveNegativeNumber
- Number type that must be negativeNonNegativeNumber
- Number type that must be non-negativeNonPositiveNumber
- Number type that must be non-positivePositiveInteger
- Integer type that must be positiveNegativeInteger
- Integer type that must be negativeNonNegativeInteger
- Integer type that must be non-negativeNonPositiveInteger
- Integer type that must be non-positiveInteger
- Integer typeNullable<T>
- Type that can be nullNumeric
- 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 patternGuardz 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")'
// ]
single
- Basic error messages (default)multi
- Detailed error messages with valuesjson
- Hierarchical error tree structureGuardz provides utility types for enhanced type safety:
import type { TypeGuardFn, TypeGuardFnConfig } from 'guardz';
// TypeGuardFn<T> - Type guard function type
// TypeGuardFnConfig - Configuration for type guards
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);
}
We welcome contributions! Please see our Contributing Guide for details.
git clone https://github.com/thiennp/guardz.git
cd guardz
npm install
npm test
This project is licensed under the MIT License - see the LICENSE file for details.
Thanks to all contributors and the TypeScript community for making this project possible.
Made with ❤️ by the Guardz Team
FAQs
A simple and lightweight TypeScript type guard library for runtime type validation.
The npm package guardz receives a total of 194 weekly downloads. As such, guardz popularity was classified as not popular.
We found that guardz demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
Research
A malicious package uses a QR code as steganography in an innovative technique.
Research
/Security News
Socket identified 80 fake candidates targeting engineering roles, including suspected North Korean operators, exposing the new reality of hiring as a security function.