Skip to main content

Overview

The validators module provides a comprehensive set of type-guard functions for runtime type checking in TypeScript. Each function not only checks the type at runtime but also acts as a type guard, allowing TypeScript to narrow types automatically.
All validator functions return boolean values and can be used as type guards in TypeScript, providing both runtime safety and compile-time type narrowing.

Type Validators

isString()

Checks if a value is a string.
function isString(arg: unknown): arg is string
arg
unknown
required
The value to check
boolean
boolean
true if the value is a string, false otherwise

Example

import { isString } from 'wapi/utils/validators';

console.log(isString('hello'));     // true
console.log(isString(123));         // false
console.log(isString(null));        // false

isNumber()

Checks if a value is a valid number (not NaN).
function isNumber(arg: unknown): arg is number
arg
unknown
required
The value to check
boolean
boolean
true if the value is a number and not NaN, false otherwise

Example

import { isNumber } from 'wapi/utils/validators';

console.log(isNumber(42));          // true
console.log(isNumber(3.14));        // true
console.log(isNumber(NaN));         // false
console.log(isNumber('123'));       // false
Note that isNumber() returns false for NaN, even though typeof NaN === 'number'. This is intentional to help catch invalid numeric operations.

isObject()

Checks if a value is an object (excluding null).
function isObject(arg: unknown): arg is object
arg
unknown
required
The value to check
boolean
boolean
true if the value is an object and not null, false otherwise

Example

import { isObject } from 'wapi/utils/validators';

console.log(isObject({ name: 'John' }));  // true
console.log(isObject([]));                // true (arrays are objects)
console.log(isObject(null));              // false
console.log(isObject('string'));          // false
Remember that arrays, functions, and class instances are also objects in JavaScript. Use isArray() if you specifically need to check for arrays.

isArray()

Checks if a value is an array.
function isArray(arg: unknown): arg is unknown[]
arg
unknown
required
The value to check
boolean
boolean
true if the value is an array, false otherwise

Example

import { isArray } from 'wapi/utils/validators';

console.log(isArray([1, 2, 3]));    // true
console.log(isArray([]));           // true
console.log(isArray({ 0: 'a' }));   // false
console.log(isArray('array'));      // false

isBuffer()

Checks if a value is a Node.js Buffer.
function isBuffer(arg: unknown): arg is Buffer
arg
unknown
required
The value to check
boolean
boolean
true if the value is a Buffer, false otherwise

Example

import { isBuffer } from 'wapi/utils/validators';

const buf = Buffer.from('hello');
const arr = new Uint8Array([1, 2, 3]);

console.log(isBuffer(buf));         // true
console.log(isBuffer(arr));         // false
console.log(isBuffer('string'));    // false

isUint8Array()

Checks if a value is a Uint8Array.
function isUint8Array(arg: unknown): arg is Uint8Array
arg
unknown
required
The value to check
boolean
boolean
true if the value is a Uint8Array, false otherwise

Example

import { isUint8Array } from 'wapi/utils/validators';

const arr = new Uint8Array([1, 2, 3]);
const buf = Buffer.from([1, 2, 3]);

console.log(isUint8Array(arr));     // true
console.log(isUint8Array(buf));     // true (Buffer extends Uint8Array)
console.log(isUint8Array([1, 2]));  // false
Node.js Buffer extends Uint8Array, so isUint8Array() will return true for Buffers. Use isBuffer() if you specifically need to distinguish Buffers from other Uint8Arrays.

isError()

Checks if a value is an Error instance.
function isError(arg: unknown): arg is Error
arg
unknown
required
The value to check
boolean
boolean
true if the value is an Error instance, false otherwise

Example

import { isError } from 'wapi/utils/validators';

console.log(isError(new Error('oops')));        // true
console.log(isError(new TypeError('wrong')));   // true
console.log(isError({ message: 'error' }));     // false
console.log(isError('error string'));           // false

Checks if a value is a valid URL.
function isLink(arg: unknown): arg is NonNullable<string>
arg
unknown
required
The value to check
boolean
boolean
true if the value can be parsed as a valid URL, false otherwise

Example

import { isLink } from 'wapi/utils/validators';

console.log(isLink('https://example.com'));         // true
console.log(isLink('http://localhost:3000'));       // true
console.log(isLink('ftp://files.example.com'));     // true
console.log(isLink('not a url'));                   // false
console.log(isLink('example.com'));                 // false (no protocol)
The URL must include a protocol (e.g., http://, https://). Plain domain names like example.com will return false.

isUUID()

Checks if a value is a valid UUID (v4 format).
function isUUID(arg: unknown): arg is UUID
arg
unknown
required
The value to check
boolean
boolean
true if the value matches the UUID v4 format, false otherwise

Example

import { isUUID } from 'wapi/utils/validators';

console.log(isUUID('550e8400-e29b-41d4-a716-446655440000'));  // true
console.log(isUUID('not-a-uuid'));                           // false
console.log(isUUID('12345'));                                // false

Common Patterns

Combining Validators

import { isObject, isString, isNumber } from 'wapi/utils/validators';

interface User {
  name: string;
  age: number;
}

function isUser(value: unknown): value is User {
  return (
    isObject(value) &&
    'name' in value &&
    isString(value.name) &&
    'age' in value &&
    isNumber(value.age)
  );
}

const data: unknown = { name: 'John', age: 30 };
if (isUser(data)) {
  console.log(`${data.name} is ${data.age} years old`);
}

Input Sanitization

import { isString, isNumber } from 'wapi/utils/validators';

function toNumber(value: unknown): number | null {
  if (isNumber(value)) {
    return value;
  }
  
  if (isString(value)) {
    const num = parseFloat(value);
    return isNumber(num) ? num : null;
  }
  
  return null;
}

command('calc', async (ctx) => {
  const num = toNumber(ctx.args[0]);
  
  if (num === null) {
    await ctx.reply('Please provide a valid number!');
    return;
  }
  
  await ctx.reply(`Result: ${num * 2}`);
});

Middleware Validators

import { isString } from 'wapi/utils/validators';
import { defineMiddleware } from 'wapi';

export const requireText = defineMiddleware(async (ctx, next) => {
  if (!isString(ctx.message.text)) {
    await ctx.reply('This command requires a text message!');
    return;
  }
  
  await next();
});

Error Recovery

import { isObject, isString } from 'wapi/utils/validators';

function getProperty(obj: unknown, key: string): unknown {
  if (!isObject(obj)) {
    return undefined;
  }
  
  return key in obj ? (obj as Record<string, unknown>)[key] : undefined;
}

function getStringProperty(obj: unknown, key: string): string | undefined {
  const value = getProperty(obj, key);
  return isString(value) ? value : undefined;
}

Type Guard Benefits

All validator functions act as TypeScript type guards, which means:
function example(value: unknown) {
  if (isString(value)) {
    // TypeScript knows value is string here
    value.toUpperCase(); // ✓ OK
  }
  
  if (isNumber(value)) {
    // TypeScript knows value is number here
    value.toFixed(2); // ✓ OK
  }
}

See Also

Build docs developers (and LLMs) love