Skip to main content

Mixed Guards

Collection of domain-specific type guards for validating common data formats and runtime environments.

Import

import {
isEmail, isEmailArray, isDateString, isUUID,
isBrowser, isNode, isURL, isBase64,
isPhoneNumber, isIPAddress, isEnvironment,
isNumericString
} from 'nhb-toolbox';

String Format Guards

isEmail

function isEmail(value: unknown): value is string

Description

Validates if a string conforms to standard email format. Uses comprehensive regex pattern covering:

  • Local part (before @)
  • Domain part (after @)
  • Top-level domain (2+ characters)
  • Common special characters (., %, +, -)

Examples

// Valid emails
isEmail('user@example.com'); // true
isEmail('first.last@sub.domain.co.uk'); // true
isEmail('user+filter@example.org'); // true

// Invalid emails
isEmail('plainstring'); // false
isEmail('user@.com'); // false
isEmail('@example.com'); // false
isEmail('user@domain'); // false

// Type narrowing
const input: unknown = 'test@example.com';
if (isEmail(input)) {
const [local, domain] = input.split('@'); // input is string
}

isEmailArray

function isEmailArray(value: unknown): value is string[]

Description

Validates that all elements in an array are valid email strings. Combines array and email validation in single operation.

Examples

// Valid cases
isEmailArray(['a@b.com', 'x@y.org']); // true
isEmailArray([]); // true (empty array considered valid)

// Invalid cases
isEmailArray(['invalid', 'a@b.com']); // false
isEmailArray('not an array'); // false

// Practical usage
function processContacts(emails: unknown) {
if (isEmailArray(emails)) {
return emails.map(sendNewsletter); // emails is string[]
}
throw new Error('Invalid email list');
}

isDateString

function isDateString(value: unknown): value is string

Description

Validates if a string can be parsed into a valid Date. More strict than direct Date parsing as it requires properly formatted date strings.

Examples

// Valid date strings
isDateString('2023-01-01'); // true
isDateString('2020-02-29T12:00:00Z'); // true (leap year)

// Invalid cases
isDateString('not a date'); // false
isDateString('2023-02-30'); // false (invalid date)
isDateString(1234567890); // false (timestamp number)

// Usage with Date conversion
function parseDate(input: unknown) {
return isDateString(input) ? new Date(input) : null;
}

isUUID

function isUUID(value: unknown): value is string

Description

Validates if a string is a version 4 UUID following RFC 4122 standard format. Checks:

  • 8-4-4-4-12 hex digit pattern
  • Version 4 marker ('4' in third group)
  • Variant marker (8, 9, a, or b in fourth group)

Examples

// Valid UUIDv4
isUUID('d9428888-122b-11e8-b642-0ed5f89f718b'); // true
isUUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8'); // true

// Invalid formats
isUUID('not-a-uuid'); // false
isUUID('12345678-1234-1234-1234-123456789abc'); // false (invalid version)
isUUID(123456789); // false

// Practical usage
interface Resource {
id: string;
name: string;
}

function validateResource(res: unknown): res is Resource {
return isObject(res) && isUUID(res.id) && isString(res.name);
}

isURL

function isURL(value: unknown): value is string

Description

Validates if a string is a properly formatted URL using the browser's URL constructor. Checks:

  • Valid protocol (http/https/ftp etc.)
  • Proper domain structure
  • Optional path/query/hash components

Examples

// Valid URLs
isURL('https://example.com'); // true
isURL('ftp://files.test/path?q=1'); // true
isURL('//cdn.domain/image.png'); // true (protocol-relative)

// Invalid URLs
isURL('example.com'); // false (missing protocol)
isURL('http://'); // false (empty domain)
isURL(123456); // false

// Safe URL creation
function createLink(href: unknown) {
return isURL(href) ? new URL(href) : null;
}

isBase64

function isBase64(value: unknown): value is string

Description

Validates if a string is properly Base64 encoded. Accepts both standard and URL-safe variants including padding.

Examples

// Valid Base64
isBase64('SGVsbG8gd29ybGQ='); // true
isBase64('YWJjMTIz'); // true
isBase64('AAECAwQF'); // true

// Invalid cases
isBase64('Not base64!'); // false
isBase64('SGVsbG8gd29ybGQ'); // false (missing padding)
isBase64({}); // false

// Decoding safely
function decodeBase64(input: unknown) {
return isBase64(input) ? atob(input) : null;
}

isPhoneNumber

function isPhoneNumber(value: unknown): value is string

Description

Validates international phone numbers using E.164 format standard. Checks:

  • Optional leading +
  • Country code (1-15 digits)
  • Subscriber number

Examples

// Valid numbers
isPhoneNumber('+1234567890'); // true
isPhoneNumber('11234567890'); // true
isPhoneNumber('+441234567890'); // true

// Invalid numbers
isPhoneNumber('123-456-7890'); // false (contains separators)
isPhoneNumber('1800FLOWERS'); // false (contains letters)
isPhoneNumber('+123'); // false (too short)

// Formatting example
function formatPhone(input: unknown) {
if (isPhoneNumber(input)) {
return input.startsWith('+') ? input : `+${input}`;
}
return null;
}

isIPAddress

function isIPAddress(value: unknown): value is string

Description

Validates both IPv4 and IPv6 address formats including:

  • IPv4 dotted notation (192.168.1.1)
  • IPv6 hexadecimal notation (2001:0db8:85a3::8a2e:0370:7334)
  • Compressed IPv6 forms
  • Does NOT validate range/scope

Examples

// Valid IPs
isIPAddress('192.168.1.1'); // true
isIPAddress('::1'); // true (IPv6 localhost)
isIPAddress('2001:db8::8a2e:370:7334'); // true

// Invalid IPs
isIPAddress('256.300.1.1'); // false (invalid octet)
isIPAddress('localhost'); // false
isIPAddress('192.168.1'); // false (incomplete)

// Usage
function blockIP(ip: unknown) {
if (isIPAddress(ip)) {
firewall.addBlock(ip); // ip is string
}
}

isNumericString

function isNumericString(value: unknown): value is `${number}`

Description

Validates if a string represents a numeric value. Checks:

  • Whole numbers (42)
  • Decimal numbers (3.14)
  • Does NOT accept:
    • Scientific notation
    • Hexadecimal
    • Leading/trailing spaces
    • Thousand separators

Examples

// Valid cases
isNumericString('42'); // true
isNumericString('3.14159'); // true
isNumericString('0.5'); // true

// Invalid cases
isNumericString('3e10'); // false
isNumericString('0xFF'); // false
isNumericString('42px'); // false

// Type-safe conversion
function toNumber(value: unknown) {
return isNumericString(value) ? Number(value) : NaN;
}

Environment Guards

isBrowser

function isBrowser(): boolean

Description

Determines if code is running in a web browser environment by checking for:

  • window object
  • document object
  • Absence of Node.js indicators

Examples

// In browser
isBrowser(); // true

// In Node.js/SSR
isBrowser(); // false

// Environment-specific logic
function getWindowSize() {
if (isBrowser()) {
return {
width: window.innerWidth,
height: window.innerHeight
};
}
return null;
}

isNode

function isNode(): boolean

Description

Determines if code is running in a Node.js environment by checking:

  • process object
  • process.versions.node
  • Absence of browser APIs

Examples

// In Node.js
isNode(); // true

// In browser
isNode(); // false

// Module loading
function loadModule() {
if (isNode()) {
return require('fs'); // Node-specific module
}
throw new Error('Node.js required');
}

isEnvironment

function isEnvironment(env: string): boolean

Description

Checks if current Node.js environment matches specified value (case-sensitive). Common values:

  • "development"
  • "production"
  • "test"

Examples

process.env.NODE_ENV = 'production';

// Matching cases
isEnvironment('production'); // true

// Non-matching cases
isEnvironment('development'); // false

// Environment-specific config
function getConfig() {
return isEnvironment('production')
? productionConfig
: developmentConfig;
}

Aliases

Main ExportAlias Names
isEmailisValidEmail
isURLisValidURL
isEnvironmentisExpectedNodeENV, isNodeENV, isNodeEnvironment

Use Cases

Form Validation

function validateContactForm(data: unknown) {
return isObjectWithKeys(data, ['name', 'email', 'phone']) &&
isNonEmptyString(data.name) &&
isEmail(data.email) &&
(isPhoneNumber(data.phone) || data.phone === '');
}

API Response Handling

interface APIUser {
id: string;
email: string;
createdAt: string;
}

function isAPIUser(data: unknown): data is APIUser {
return isObjectWithKeys(data, ['id', 'email', 'createdAt']) &&
isUUID(data.id) &&
isEmail(data.email) &&
isDateString(data.createdAt);
}

Environment-Specific Code

function logger(message: string) {
if (isEnvironment('development')) {
console.debug(`[DEV] ${message}`);
} else if (isBrowser()) {
sendToAnalytics(message);
}
}

Notes

  1. Validation Strictness: All regex patterns balance correctness with common real-world usage
  2. Performance: Optimized validation logic with early returns
  3. Type Safety: Guards use TypeScript type predicates for proper narrowing
  4. International Support: Phone and email validations handle international formats
  5. Edge Cases: All guards handle null/undefined and invalid types properly