diff --git a/src/array/sum.test.ts b/src/array/sum.test.ts index ea43b61..c6d1815 100644 --- a/src/array/sum.test.ts +++ b/src/array/sum.test.ts @@ -54,6 +54,15 @@ describe("sum", () => { // Then we get back the sum of the numbers expect(result).toBe(18); }); + + it("works for bigints", () => { + // Given an array of bigints and undefined values + const a = [5n, undefined, 6n, 7n]; + // When we call sum + const result = a.sum(); + // Then we get back the sum of the bigints as a bigint + expect(result).toBe(18n); + }); }); describe("maybeSum", () => { @@ -110,4 +119,13 @@ describe("maybeSum", () => { // Then we get back the maybeSum of the numbers expect(result).toBe(18); }); + + it("works for bigints", () => { + // Given an array of bigints and undefined values + const a = [5n, undefined, 6n, 7n]; + // When we call maybeSum + const result = a.maybeSum(); + // Then we get back the sum of the bigints as a bigint + expect(result).toBe(18n); + }); }); diff --git a/src/array/sum.ts b/src/array/sum.ts index b856b7e..6cb2a4e 100644 --- a/src/array/sum.ts +++ b/src/array/sum.ts @@ -6,6 +6,9 @@ declare global { sum(this: (number | undefined)[]): number; sum(f: CallbackFn): number; sum(f: CallbackFn>): Promise; + sum(this: (bigint | undefined)[]): bigint; + sum(f: CallbackFn): bigint; + sum(f: CallbackFn>): Promise; /** * Sums numbers but will return `undefined` if either a) there are no numbers or b) they are all * `null` or `undefined`. @@ -17,12 +20,18 @@ declare global { maybeSum(this: (number | undefined)[]): number | undefined; maybeSum(f: CallbackFn): number | undefined; maybeSum(f: CallbackFn>): Promise; + maybeSum(this: (bigint | undefined)[]): bigint | undefined; + maybeSum(f: CallbackFn): bigint | undefined; + maybeSum(f: CallbackFn>): Promise; } interface ReadonlyArray { - sum(this: (number | undefined)[]): number; + sum(this: readonly (number | undefined)[]): number; sum(f: CallbackFnRO): number; sum(f: CallbackFnRO>): Promise; + sum(this: (bigint | undefined)[]): bigint; + sum(f: CallbackFn): bigint; + sum(f: CallbackFn>): Promise; /** * Sums numbers but will return `undefined` if either a) there are no numbers or b) they are all * `null` or `undefined`. @@ -31,23 +40,36 @@ declare global { * i.e. not being able to tell "is this zero b/c someone typed zero in?" vs. "is this zero b/c it * just doesn't have a value yet"? */ - maybeSum(this: (number | undefined)[]): number | undefined; + maybeSum(this: readonly (number | undefined)[]): number | undefined; maybeSum(f: CallbackFnRO): number | undefined; maybeSum(f: CallbackFnRO>): Promise; + maybeSum(this: readonly (bigint | undefined)[]): bigint | undefined; + maybeSum(f: CallbackFn): bigint | undefined; + maybeSum(f: CallbackFn>): Promise; } } function sum(this: R[]): number; function sum(f: CallbackFn): number; function sum(f: CallbackFn>): Promise; -function sum( +function sum(this: R[]): bigint; +function sum(f: CallbackFn): bigint; +function sum(f: CallbackFn>): Promise; +function sum( this: T[] | R[], fn?: CallbackFn>, -): MaybePromise { +): MaybePromise { const promisesOrNumbers = fn ? (this.map(fn as any) as R[] | Promise[]) : (this as R[]); - return maybePromiseAllThen(promisesOrNumbers, (numbers) => - numbers.reduce((result: number, number) => result + (number ?? 0), 0), - ); + return maybePromiseAllThen(promisesOrNumbers, (numbers) => { + let sum: bigint | number | undefined = numbers[0]; + for (let i = 1; i < numbers.length; i++) { + const number = numbers[i]; + if (number !== undefined) { + sum = (((sum ?? (typeof number === "bigint" ? 0n : 0)) as any) + number) as any; + } + } + return sum ?? 0; + }); } Array.prototype.sum = sum; @@ -55,16 +77,24 @@ Array.prototype.sum = sum; function maybeSum(this: R[]): R; function maybeSum(f: CallbackFn): R; function maybeSum(f: CallbackFn>): Promise; -function maybeSum( +function maybeSum(this: R[]): R; +function maybeSum(f: CallbackFn): R; +function maybeSum(f: CallbackFn>): Promise; +function maybeSum( this: T[] | R[], fn?: CallbackFn>, -): MaybePromise { +): MaybePromise { const promisesOrNumbers = fn ? (this.map(fn as any) as R[] | Promise[]) : (this as R[]); - return maybePromiseAllThen(promisesOrNumbers, (numbers) => - numbers.every((n) => n === undefined) - ? undefined - : numbers.reduce((result: number, number) => result + (number ?? 0), 0), - ); + return maybePromiseAllThen(promisesOrNumbers, (numbers) => { + let sum: bigint | number | undefined = numbers[0]; + for (let i = 1; i < numbers.length; i++) { + const number = numbers[i]; + if (number !== undefined) { + sum = (((sum ?? (typeof number === "bigint" ? 0n : 0)) as any) + number) as any; + } + } + return sum; + }); } Array.prototype.maybeSum = maybeSum;