Write a function range(start, end, step) that returns an array of numbers starting at start, advancing by step, and stopping before it reaches end. It's the same idea as Python's range or Lodash's _.range: you describe an arithmetic progression with three numbers and get back the list of values it would visit. end is exclusive — range(0, 5) returns [0, 1, 2, 3, 4], never including 5.
function range(
start: number, // first value of the output (inclusive)
end: number, // upper or lower bound (exclusive)
step?: number, // amount to add each iteration; defaults to 1
): number[];
range(0, 5); // [0, 1, 2, 3, 4]
range(0, 10, 2); // [0, 2, 4, 6, 8]
range(1, 4); // [1, 2, 3]
range(3, 3); // [] — empty range when start === end
range(5, 0, -1); // [5, 4, 3, 2, 1]
range(0, 5, -1); // [] — step direction doesn't reach end
range(0, 0, 0); // throws — step of 0 would loop forever
step, treat it as 1. Don't accept undefined and silently produce wrong output.end is exclusive. The output never contains end itself. range(0, 3) returns [0, 1, 2], not [0, 1, 2, 3].step walks from start down to end; the same exclusivity rule applies.0 must be rejected. Throw a RangeError — a zero step would never advance toward end and produce an infinite loop.[]. If step points the wrong way (positive step but end < start, or negative step but end > start), return an empty array. Don't throw.NaN, strings, or non-finite values — the tests only pass real numbers.