CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sindresorhus--is

Type check values with comprehensive TypeScript type guards and runtime assertions

Pending
Overview
Eval results
Files

numbers.mddocs/

Numbers and Math

Specialized number validation including integers, safe integers, positive/negative numbers, even/odd checks, range validation, and mathematical properties.

Capabilities

Integer Type Checking

Check if a value is an integer or safe integer.

/**
 * Check if value is an integer
 * @param value - Value to check
 * @returns True if value is integer
 */
function isInteger(value: unknown): value is number;

/**
 * Check if value is a safe integer (within safe integer range)
 * @param value - Value to check
 * @returns True if value is safe integer
 */
function isSafeInteger(value: unknown): value is number;

Usage Examples:

import is from '@sindresorhus/is';

is.integer(42); // => true
is.integer(3.14); // => false
is.integer(Number.MAX_VALUE); // => false (too large to be precise)

is.safeInteger(42); // => true
is.safeInteger(Number.MAX_SAFE_INTEGER); // => true
is.safeInteger(Number.MAX_SAFE_INTEGER + 1); // => false
is.safeInteger(3.14); // => false

// Type guard usage
function processArrayIndex(index: unknown) {
  if (is.safeInteger(index) && index >= 0) {
    // index is now typed as number and guaranteed to be safe
    return `Item at index ${index}`;
  }
  throw new Error('Invalid array index');
}

Sign-based Number Checking

Check if numbers are positive or negative.

/**
 * Check if value is a positive number
 * @param value - Value to check
 * @returns True if value is positive number
 */
function isPositiveNumber(value: unknown): value is number;

/**
 * Check if value is a negative number
 * @param value - Value to check
 * @returns True if value is negative number
 */
function isNegativeNumber(value: unknown): value is number;

Usage Examples:

import is from '@sindresorhus/is';

is.positiveNumber(42); // => true
is.positiveNumber(0); // => false
is.positiveNumber(-5); // => false
is.positiveNumber('42'); // => false

is.negativeNumber(-42); // => true
is.negativeNumber(0); // => false
is.negativeNumber(5); // => false

// Type guard usage
function calculateDiscount(amount: unknown, discount: unknown) {
  if (is.positiveNumber(amount) && is.positiveNumber(discount)) {
    // Both are now typed as positive numbers
    return amount - (amount * discount / 100);
  }
  throw new Error('Amount and discount must be positive numbers');
}

Even and Odd Integer Checking

Check if integers are even or odd.

/**
 * Check if value is an even integer
 * @param value - Value to check
 * @returns True if value is even integer
 */
function isEvenInteger(value: unknown): value is number;

/**
 * Check if value is an odd integer
 * @param value - Value to check
 * @returns True if value is odd integer
 */
function isOddInteger(value: unknown): value is number;

Usage Examples:

import is from '@sindresorhus/is';

is.evenInteger(2); // => true
is.evenInteger(3); // => false
is.evenInteger(0); // => true
is.evenInteger(2.5); // => false

is.oddInteger(3); // => true
is.oddInteger(2); // => false
is.oddInteger(1.5); // => false

// Type guard usage
function processNumbers(numbers: unknown[]) {
  const evens = numbers.filter(is.evenInteger);
  const odds = numbers.filter(is.oddInteger);
  
  console.log('Even numbers:', evens);
  console.log('Odd numbers:', odds);
}

Infinity Checking

Check if a value is positive or negative infinity.

/**
 * Check if value is Infinity or -Infinity
 * @param value - Value to check
 * @returns True if value is infinite
 */
function isInfinite(value: unknown): value is number;

Usage Examples:

import is from '@sindresorhus/is';

is.infinite(Infinity); // => true
is.infinite(-Infinity); // => true
is.infinite(Number.POSITIVE_INFINITY); // => true
is.infinite(Number.NEGATIVE_INFINITY); // => true
is.infinite(42); // => false
is.infinite(NaN); // => false

// Type guard usage
function safeDivision(a: number, b: number) {
  const result = a / b;
  if (is.infinite(result)) {
    throw new Error('Division resulted in infinity');
  }
  return result;
}

Range Validation

Check if a number is within a specified range.

/**
 * Check if number is within specified range
 * @param value - Number to check
 * @param range - Range as single number (0 to range) or [min, max] tuple
 * @returns True if value is in range
 */
function isInRange(value: number, range: number | [number, number]): value is number;

Usage Examples:

import is from '@sindresorhus/is';

// Single number range (0 to range)
is.inRange(5, 10); // => true (0 <= 5 <= 10)
is.inRange(-2, 10); // => false (negative values not allowed)
is.inRange(15, 10); // => false (above range)

// Array range [min, max]
is.inRange(5, [0, 10]); // => true
is.inRange(5, [10, 20]); // => false
is.inRange(15, [10, 20]); // => true

// Range order doesn't matter
is.inRange(5, [10, 0]); // => true (same as [0, 10])

// Type guard usage (value is already number)
function processScore(score: number) {
  if (is.inRange(score, [0, 100])) {
    // score is guaranteed to be 0-100
    const grade = score >= 90 ? 'A' : score >= 80 ? 'B' : 'C';
    return grade;
  }
  throw new Error('Score must be between 0 and 100');
}

// Validation with unknown input
function validateAge(age: unknown) {
  if (is.number(age) && is.inRange(age, [0, 120])) {
    return age; // Valid age
  }
  throw new Error('Age must be a number between 0 and 120');
}

Numeric String Validation

Check if a string represents a valid number.

/**
 * Check if string represents a valid number
 * @param value - Value to check
 * @returns True if value is numeric string
 */
function isNumericString(value: unknown): value is `${number}`;

Usage Examples:

import is from '@sindresorhus/is';

is.numericString('42'); // => true
is.numericString('3.14'); // => true
is.numericString('-123'); // => true
is.numericString('1e10'); // => true
is.numericString('Infinity'); // => true
is.numericString('-Infinity'); // => true

is.numericString('NaN'); // => false
is.numericString('42px'); // => false
is.numericString(''); // => false
is.numericString('   '); // => false
is.numericString('hello'); // => false

// Type guard usage
function parseNumber(input: unknown) {
  if (is.numericString(input)) {
    // input is now typed as `${number}`
    const num = Number(input);
    return num;
  }
  throw new Error('Input is not a numeric string');
}

// Form validation
function validateFormInput(input: unknown) {
  if (is.string(input) && is.numericString(input)) {
    return Number(input);
  }
  return null;
}

Usage Patterns

Number Validation Chain

import is from '@sindresorhus/is';

function validatePositiveInteger(value: unknown): number {
  if (!is.number(value)) {
    throw new Error('Value must be a number');
  }
  
  if (!is.integer(value)) {
    throw new Error('Value must be an integer');
  }
  
  if (!is.positiveNumber(value)) {
    throw new Error('Value must be positive');
  }
  
  return value;
}

// Usage
try {
  const count = validatePositiveInteger(42); // OK
  const invalid = validatePositiveInteger(-5); // throws
} catch (error) {
  console.error(error.message);
}

Mathematical Operations

import is from '@sindresorhus/is';

function factorial(n: unknown): number {
  if (!is.number(n) || !is.integer(n) || !is.positiveNumber(n)) {
    throw new Error('Factorial requires a positive integer');
  }
  
  if (n === 0) return 1;
  return n * factorial(n - 1);
}

function gcd(a: unknown, b: unknown): number {
  if (!is.integer(a) || !is.integer(b)) {
    throw new Error('GCD requires integers');
  }
  
  const absA = Math.abs(a as number);
  const absB = Math.abs(b as number);
  
  return absB === 0 ? absA : gcd(absB, absA % absB);
}

Range-based Processing

import is from '@sindresorhus/is';

function categorizeNumbers(numbers: unknown[]): {
  positive: number[];
  negative: number[];
  zero: number[];
  invalid: unknown[];
} {
  const result = {
    positive: [] as number[],
    negative: [] as number[], 
    zero: [] as number[],
    invalid: [] as unknown[]
  };
  
  for (const num of numbers) {
    if (!is.number(num)) {
      result.invalid.push(num);
    } else if (is.positiveNumber(num)) {
      result.positive.push(num);
    } else if (is.negativeNumber(num)) {
      result.negative.push(num);
    } else {
      result.zero.push(num); // Must be 0
    }
  }
  
  return result;
}

Safe Math Operations

import is from '@sindresorhus/is';

function safeMath(a: unknown, b: unknown, operation: string): number {
  if (!is.number(a) || !is.number(b)) {
    throw new Error('Both operands must be numbers');
  }
  
  if (!is.safeInteger(a) || !is.safeInteger(b)) {
    throw new Error('Operands must be safe integers');
  }
  
  let result: number;
  switch (operation) {
    case '+':
      result = a + b;
      break;
    case '*':
      result = a * b;
      break;
    default:
      throw new Error('Unsupported operation');
  }
  
  if (!is.safeInteger(result)) {
    throw new Error('Result exceeds safe integer range');
  }
  
  return result;
}

Notes

  • isInteger() uses Number.isInteger() internally
  • isSafeInteger() checks if number is within Number.MAX_SAFE_INTEGER range
  • Even/odd checking only works with integers; non-integers return false
  • isInRange() accepts the number to check as first parameter (must already be a number)
  • Range validation with single number creates range from 0 to that number
  • Range validation with array accepts [min, max] in any order
  • Numeric string validation excludes 'NaN' but includes 'Infinity' and '-Infinity'
  • All number checks work with TypeScript type guards for compile-time type narrowing

Install with Tessl CLI

npx tessl i tessl/npm-sindresorhus--is

docs

assertions.md

async.md

collections.md

index.md

numbers.md

objects.md

primitives.md

strings.md

typed-arrays.md

validation.md

web-apis.md

tile.json