← Download MyJS

MyJS block

clamp 1.0.0

Limits a value to a range: `min` if it's below the range, `max` if it's above it, and the value itself otherwise.

Download with this
Exports
clamp
Works in
Browser and Node.js
The code of version 1.0.0
/**
 * Limits a value to a range: `min` if it's below the range, `max` if it's
 * above it, and the value itself otherwise.
 *
 * For numbers it works like the proposed `Math.clamp()`: `NaN` for any `NaN`
 * argument, and `-0` and `+0` are kept apart (`clamp(-0, 0, 10)` is `+0`).
 * Unlike the proposal, it also works on anything `<` and `>` can compare:
 * BigInts, strings (alphabetically), Dates, and BigInts mixed with numbers.
 * When the value is outside the range, the bound itself is returned (the same
 * Date object, for example).
 *
 * A bound that's `undefined` (or `-Infinity`/`Infinity` for numbers) means no
 * limit on that side. `null` isn't a missing bound: it counts as 0. When both
 * bounds are strings they're compared alphabetically, so numbers in strings
 * don't work as expected (`clamp(5, '9', '10')` throws, because `'9'` comes
 * after `'10'`).
 *
 * @param {number|bigint|string|Date|*} value
 *   The value to limit.
 * @param {number|bigint|string|Date|*} [min]
 *   The lowest value allowed, or `undefined` for no lower limit.
 * @param {number|bigint|string|Date|*} [max]
 *   The highest value allowed, or `undefined` for no upper limit.
 * @returns {number|bigint|string|Date|*}
 *   `min` if `value` is below it, `max` if `value` is above it, otherwise
 *   `value` (or `NaN` if any of them are `NaN` numbers).
 * @throws {RangeError}
 *   If `min` is greater than `max` (including `min` being `+0` and `max` `-0`).
 *
 * @example
 * clamp(15, 0, 10);         // 10
 * clamp(-5, 0, 10);         // 0
 * clamp(5, 0, 10);          // 5
 * clamp(5, 0, Infinity);    // 5
 * clamp(NaN, 0, 10);        // NaN
 * clamp(-0, 0, 10);         // 0 (+0)
 *
 * @example
 * clamp(15n, 0n, 10n);      // 10n
 * clamp('m', 'a', 'f');     // 'f'
 * clamp(150, undefined, 100); // 100 (no lower limit)
 *
 * @example
 * // Keeps a date within this year
 * const start = new Date(2026, 0, 1);
 * const end = new Date(2026, 11, 31);
 * clamp(new Date(2031, 5, 1), start, end) === end; // true
 *
 * @example
 * clamp(5, 10, 0);          // throws a RangeError
 */
function clamp(value, min, max) {
  // min > max misses +0 and -0, which are equal to <, so they're checked by sign
  if (min > max || (min === 0 && max === 0 && 1 / min > 1 / max)) {
    throw new RangeError('The min must be less than or equal to max.');
  }
  return (typeof value === 'number' && typeof min === 'number' && typeof max === 'number')
    ? Math.max(min, Math.min(value, max))
    : value < min
      ? min
      : value > max
        ? max
        : value;
}

Versions

  1. 1.0.0 Oct 16, 2026

    Initial

JSDoc