Type checking utilities and type guards providing runtime validation, type narrowing, and safe type checking operations.
Type guards for checking JavaScript primitive types with TypeScript type narrowing.
/**
* Check if value is defined (not undefined)
* @param val - Value to check
* @returns True if value is not undefined
*/
function isDef<T = any>(val?: T): val is T;
/**
* Check if value is boolean
* @param val - Value to check
* @returns True if value is boolean
*/
function isBoolean(val: any): val is boolean;
/**
* Check if value is function
* @param val - Value to check
* @returns True if value is function
*/
function isFunction<T extends Function = Function>(val: any): val is T;
/**
* Check if value is number
* @param val - Value to check
* @returns True if value is number
*/
function isNumber(val: any): val is number;
/**
* Check if value is string
* @param val - Value to check
* @returns True if value is string
*/
function isString(val: unknown): val is string;
/**
* Check if value is plain object
* @param val - Value to check
* @returns True if value is plain object
*/
function isObject(val: any): val is object;
/**
* Check if value is undefined
* @param val - Value to check
* @returns True if value is undefined
*/
function isUndefined(val: any): val is undefined;
/**
* Check if value is null
* @param val - Value to check
* @returns True if value is null
*/
function isNull(val: any): val is null;Usage Examples:
import { isDef, isBoolean, isNumber, isString, isObject } from "@antfu/utils";
function processValue(value: unknown) {
if (isString(value)) {
return value.toUpperCase(); // TypeScript knows value is string
}
if (isNumber(value)) {
return value * 2; // TypeScript knows value is number
}
if (isObject(value)) {
return Object.keys(value); // TypeScript knows value is object
}
return null;
}
// Safe optional value handling
function handleOptional(val?: string) {
if (isDef(val)) {
console.log(val.length); // TypeScript knows val is string (not undefined)
}
}
// Type-safe function checking
function maybeCall(fn: unknown, ...args: any[]) {
if (isFunction(fn)) {
return fn(...args); // TypeScript knows fn is callable
}
return undefined;
}Type guards for more complex JavaScript types and objects.
/**
* Check if value is RegExp
* @param val - Value to check
* @returns True if value is RegExp
*/
function isRegExp(val: any): val is RegExp;
/**
* Check if value is Date
* @param val - Value to check
* @returns True if value is Date
*/
function isDate(val: any): val is Date;
/**
* Check if value is primitive (string, number, boolean, symbol, bigint, null, undefined)
* @param val - Value to check
* @returns True if value is primitive
*/
function isPrimitive(val: any): val is string | number | boolean | symbol | bigint | null | undefined;Usage Examples:
import { isRegExp, isDate, isPrimitive } from "@antfu/utils";
function processInput(input: unknown) {
if (isDate(input)) {
return input.toISOString(); // TypeScript knows input is Date
}
if (isRegExp(input)) {
return input.source; // TypeScript knows input is RegExp
}
if (isPrimitive(input)) {
return String(input); // Safe to convert primitives to string
}
return "Complex object";
}
// Pattern matching with type guards
function formatValue(value: unknown): string {
if (isDate(value)) return value.toLocaleDateString();
if (isRegExp(value)) return `Pattern: ${value.source}`;
if (isPrimitive(value)) return String(value);
return "[Object]";
}Type guards for checking runtime environment characteristics.
/**
* Check if value is Window object (browser only)
* @param val - Value to check
* @returns True if value is Window object
*/
function isWindow(val: any): boolean;
/**
* Constant indicating if running in browser environment
*/
const isBrowser: boolean;Usage Examples:
import { isWindow, isBrowser } from "@antfu/utils";
// Environment-aware code
if (isBrowser) {
// Browser-specific code
const element = document.getElementById('app');
if (isWindow(globalThis)) {
console.log('Running in browser window context');
}
} else {
// Node.js or other environment
console.log('Running in non-browser environment');
}
// Safe DOM manipulation
function setupUI() {
if (isBrowser && typeof document !== 'undefined') {
const button = document.createElement('button');
button.textContent = 'Click me';
document.body.appendChild(button);
}
}Type guards specifically designed for filtering out null, undefined, and falsy values.
/**
* Type guard to filter out null-ish values
* @param v - Value to check
* @returns True if value is not null or undefined
*/
function notNullish<T>(v: T | null | undefined): v is NonNullable<T>;
/**
* Type guard to filter out null values
* @param v - Value to check
* @returns True if value is not null
*/
function noNull<T>(v: T | null): v is Exclude<T, null>;
/**
* Type guard to filter out undefined values
* @param v - Value to check
* @returns True if value is not undefined
*/
function notUndefined<T>(v: T): v is Exclude<T, undefined>;
/**
* Type guard to filter out falsy values
* @param v - Value to check
* @returns True if value is truthy
*/
function isTruthy<T>(v: T): v is NonNullable<T>;Usage Examples:
import { notNullish, noNull, notUndefined, isTruthy } from "@antfu/utils";
// Filter arrays with type safety
const mixedArray: (string | null | undefined)[] = ["hello", null, "world", undefined, ""];
// Remove null and undefined
const definedValues = mixedArray.filter(notNullish);
// Type: string[], values: ["hello", "world", ""]
// Remove only null values
const notNullValues = mixedArray.filter(noNull);
// Type: (string | undefined)[], values: ["hello", "world", undefined, ""]
// Remove only undefined values
const notUndefinedValues = mixedArray.filter(notUndefined);
// Type: (string | null)[], values: ["hello", null, "world", ""]
// Remove all falsy values
const truthyValues = mixedArray.filter(isTruthy);
// Type: string[], values: ["hello", "world"]
// Safe optional chaining alternative
function processUser(user: { name?: string; email?: string | null }) {
const fields = [user.name, user.email].filter(notNullish);
// fields is guaranteed to be string[]
return fields.map(field => field.toUpperCase());
}
// Array processing with type narrowing
function processItems<T>(items: (T | null | undefined)[]): T[] {
return items
.filter(notNullish) // Remove null/undefined
.filter(isTruthy); // Remove remaining falsy values
}Core utility functions for assertions, type inspection, and basic operations.
/**
* Assert a condition is true, throwing an error with message if not
* @param condition - Condition to assert
* @param message - Error message if assertion fails
* @throws Error if condition is false
*/
function assert(condition: boolean, message: string): asserts condition;
/**
* Get the string representation of a value using Object.prototype.toString
* @param v - Value to get string representation of
* @returns String representation like "[object Array]"
*/
function toString(v: any): string;
/**
* Get the type name of a value
* @param v - Value to get type name for
* @returns Type name as string (e.g., "array", "object", "string")
*/
function getTypeName(v: any): string;
/**
* No-operation function that does nothing
*/
function noop(): void;Usage Examples:
import { assert, toString, getTypeName, noop } from "@antfu/utils";
// Assertions in code
function divide(a: number, b: number): number {
assert(b !== 0, "Division by zero is not allowed");
return a / b;
}
// Type inspection
const typeString = toString([1, 2, 3]); // "[object Array]"
const typeName = getTypeName([1, 2, 3]); // "array"
const objType = getTypeName({ a: 1 }); // "object"
const primitiveType = getTypeName("hello"); // "string"
// No-op placeholder
let callback: () => void = noop; // Safe default
function setupHandler(handler: () => void = noop) {
// Use noop as default to avoid null checks
document.addEventListener('click', handler);
}
// Type-safe assertions
function processUser(user: unknown): User {
assert(typeof user === 'object' && user !== null, 'User must be an object');
assert('id' in user, 'User must have an id');
return user as User;
}
// Debug type inspection
function debugValue(value: unknown): void {
console.log(`Value: ${value}`);
console.log(`Type: ${getTypeName(value)}`);
console.log(`ToString: ${toString(value)}`);
}Advanced equality checking for complex data structures.
/**
* Deep equality comparison for complex objects and arrays
* @param value1 - First value to compare
* @param value2 - Second value to compare
* @returns True if values are deeply equal
*/
function isDeepEqual(value1: any, value2: any): boolean;Usage Examples:
import { isDeepEqual } from "@antfu/utils";
// Compare primitive values
console.log(isDeepEqual(1, 1)); // true
console.log(isDeepEqual("hello", "hello")); // true
console.log(isDeepEqual(1, "1")); // false
// Compare arrays
const arr1 = [1, 2, { a: 3 }];
const arr2 = [1, 2, { a: 3 }];
const arr3 = [1, 2, { a: 4 }];
console.log(isDeepEqual(arr1, arr2)); // true
console.log(isDeepEqual(arr1, arr3)); // false
// Compare objects
const obj1 = { name: "Alice", details: { age: 30, city: "NYC" } };
const obj2 = { name: "Alice", details: { age: 30, city: "NYC" } };
const obj3 = { name: "Alice", details: { age: 30, city: "LA" } };
console.log(isDeepEqual(obj1, obj2)); // true
console.log(isDeepEqual(obj1, obj3)); // false
// Useful for React/Vue optimization
function shouldUpdateComponent(prevProps: any, nextProps: any) {
return !isDeepEqual(prevProps, nextProps);
}
// State comparison in reducers
function updateState(currentState: any, newState: any) {
if (isDeepEqual(currentState, newState)) {
return currentState; // No change, return same reference
}
return newState;
}