# New Proposal: Number.range (Yes, range again)

I end up writing a range function in virtually every project I use, so yeah, I think this is worthwhile.

My own preferences, based on Python precedence:

Number.range(end) === Number.range(0, end, 1) Number.range(start, end) === Number.range(start, end, Math.sign(end-start)) Number.range(start, end, step) => { if start < end && step > 0: yield all (start + k*step), for k from 0

to infinity, less than end elif start > end && step < 0: yield all (start + k*step), for k from

0 to infinity, greater than end else: yield nothing }

So:

- [...Number.range(5)] evaluates to [0, 1, 2, 3, 4]
- [...Number.range(0)] evaluates to []
- [...Number.range(-5)] evaluates to []
- [...Number.range(1, -3)] evaluates to [1, 0, -1, -2]
- [...Number.range(-3, 1)] evaluates to [-3, -2, -1, 0]
- [...Number.range(1, 1)] evaluates to []
- [...Number.range(0, 10, 5)] evaluates to [0, 5]
- [...Number.range(0, 10, -5)] evaluates to []

Quick, simple TypeScript range function (with overloads, of course).

```
export function range(end: number): IterableIterator<number>;
export function range(start: number, end: number): IterableIterator<number>;
export function range(start: number, end: number, step: number):
IterableIterator<number>;
export function* range(start: number, end?: number, step?: number):
IterableIterator<number> {
// overload #1
if (end === undefined) {
[start, end, step] = [0, start, 1];
}
// overload #2
if (step === undefined) {
step = Math.sign(end - start);
}
// ensure we have the appropriate types
if (typeof start !== 'number' || typeof end !== 'number' || typeof step
!== 'number') {
throw new TypeError('all parameters must be of type number');
}
while ((start < end && step > 0) || (start > end && step < 0)) {
yield start;
start += step;
}
}
```

IMO, we should focus on building up a JavaScript standard library that has tons of useful utilities like this, rather than continue to add methods onto namespaces. Perhaps that's just me, though.

Jacob Pratt

Oh, I'm not here to find out how to implement a range in detail. That's the trivial things, I want to first make it become a stage 0 proposal, then we can discuss if we need some overload or how to deal with the edge cases. Ps, does Pratt mean we should add it as a standard library in the stage 1 standard libraray proposal?

I'm not saying we should add it on to that proposal, but rather saying that I think more effort should be put into a standard library where things like this don't need to go through a full standards process. That's just my opinion, and borderline on-topic for this specific suggestion.

I'm absolutely in favor of having a `range`

method, it's just *where* it
should be that I differ.

Jacob Pratt

It's not a "standard library" unless every part of it has gone through a full standards process.

cf tc39/proposal-slice-notation#19 which would be more powerful as a literal

Hello everyone. I've searched for the mailing list, there are some discussions add

`new Range`

or`a ... b`

into the language but not become a formal proposal.I've made a full demo(polyfill) these days. Anyone interested?

Preview:

`for (let i of Number.range(1, 5)) console.log(i)`

And there is an extended version that let range support number range check

`if ( x in Number.range(0, 100) )`

. About usage, test case, and demo of the extended version is posted on gist.gist.github.com/Jack-Works/aa8d4c5dbd0e8cdd415783de8d922451

( This proposal can also/or add an new operator instead.

`Number.range(x, y)`

=>`x...y`

`Number.range(x, y, z)`

=>`(x...y).step(z)`

or`x...z->y`

or somethingelse, and other behavior keep same with the Number.range implmentation in the gist )

Here is the base version of the proposal

`Number.range = function*(from, to, step) { if ( typeof from !== 'number' && typeof from !== 'bigint' && (typeof to !== 'number' && typeof to !== 'bigint') && (typeof step !== 'number' && typeof step !== 'bigint' && typeof step !== 'undefined') ) throw new TypeError('All parameters must be a number or a BigInt') if (typeof from === 'bigint' && typeof step === 'undefined') step = 1n else if (typeof from === 'number' && typeof step === 'undefined') step = 1 if (typeof from !== typeof to || typeof from !== typeof step) throw new TypeError('Type of all parameters must be the same') if (typeof from === "number" && Number.isNaN(from) || Number.isNaN(to) || Number.isNaN(step)) return; // Quit early with no value yield // Math.abs does not support BigInt. const abs = x => (x >= (typeof x === 'bigint' ? 0n : 0) ? x : -x) const increase = to > from // Ignore the symbol if (increase) step = abs(step) else step = -abs(step) let count = typeof from === 'bigint' ? 1n : 1 let now = from while (increase ? !(now >= to) : !(to >= now)) { yield now now = from + step * count count++ } }`