Skip to content

Commit

Permalink
feat: Added bigint support to sum (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
zgavin authored Jun 11, 2024
1 parent 9896b1c commit 2866b99
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 14 deletions.
18 changes: 18 additions & 0 deletions src/array/sum.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand Down Expand Up @@ -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);
});
});
58 changes: 44 additions & 14 deletions src/array/sum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ declare global {
sum(this: (number | undefined)[]): number;
sum(f: CallbackFn<T, number | undefined>): number;
sum(f: CallbackFn<T, Promise<number | undefined>>): Promise<number>;
sum(this: (bigint | undefined)[]): bigint;
sum(f: CallbackFn<T, bigint | undefined>): bigint;
sum(f: CallbackFn<T, Promise<bigint | undefined>>): Promise<bigint>;
/**
* Sums numbers but will return `undefined` if either a) there are no numbers or b) they are all
* `null` or `undefined`.
Expand All @@ -17,12 +20,18 @@ declare global {
maybeSum(this: (number | undefined)[]): number | undefined;
maybeSum(f: CallbackFn<T, number | undefined>): number | undefined;
maybeSum(f: CallbackFn<T, Promise<number | undefined>>): Promise<number | undefined>;
maybeSum(this: (bigint | undefined)[]): bigint | undefined;
maybeSum(f: CallbackFn<T, bigint | undefined>): bigint | undefined;
maybeSum(f: CallbackFn<T, Promise<bigint | undefined>>): Promise<bigint | undefined>;
}

interface ReadonlyArray<T> {
sum(this: (number | undefined)[]): number;
sum(this: readonly (number | undefined)[]): number;
sum(f: CallbackFnRO<T, number | undefined>): number;
sum(f: CallbackFnRO<T, Promise<number | undefined>>): Promise<number>;
sum(this: (bigint | undefined)[]): bigint;
sum(f: CallbackFn<T, bigint | undefined>): bigint;
sum(f: CallbackFn<T, Promise<bigint | undefined>>): Promise<bigint>;
/**
* Sums numbers but will return `undefined` if either a) there are no numbers or b) they are all
* `null` or `undefined`.
Expand All @@ -31,40 +40,61 @@ 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<T, number | undefined>): number | undefined;
maybeSum(f: CallbackFnRO<T, Promise<number | undefined>>): Promise<number | undefined>;
maybeSum(this: readonly (bigint | undefined)[]): bigint | undefined;
maybeSum(f: CallbackFn<T, bigint | undefined>): bigint | undefined;
maybeSum(f: CallbackFn<T, Promise<bigint | undefined>>): Promise<bigint | undefined>;
}
}

function sum<T, R extends number | undefined>(this: R[]): number;
function sum<T, R extends number | undefined>(f: CallbackFn<T, R>): number;
function sum<T, R extends number | undefined>(f: CallbackFn<T, Promise<R>>): Promise<number>;
function sum<T, R extends number | undefined>(
function sum<T, R extends bigint | undefined>(this: R[]): bigint;
function sum<T, R extends bigint | undefined>(f: CallbackFn<T, R>): bigint;
function sum<T, R extends bigint | undefined>(f: CallbackFn<T, Promise<R>>): Promise<bigint>;
function sum<T, R extends number | bigint | undefined>(
this: T[] | R[],
fn?: CallbackFn<T, MaybePromise<R>>,
): MaybePromise<number> {
): MaybePromise<number | bigint> {
const promisesOrNumbers = fn ? (this.map(fn as any) as R[] | Promise<R>[]) : (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;

function maybeSum<T, R extends number | undefined>(this: R[]): R;
function maybeSum<T, R extends number | undefined>(f: CallbackFn<T, R>): R;
function maybeSum<T, R extends number | undefined>(f: CallbackFn<T, Promise<R>>): Promise<R>;
function maybeSum<T, R extends number | undefined>(
function maybeSum<T, R extends bigint | undefined>(this: R[]): R;
function maybeSum<T, R extends bigint | undefined>(f: CallbackFn<T, R>): R;
function maybeSum<T, R extends bigint | undefined>(f: CallbackFn<T, Promise<R>>): Promise<R>;
function maybeSum<T, R extends number | bigint | undefined>(
this: T[] | R[],
fn?: CallbackFn<T, MaybePromise<R>>,
): MaybePromise<number | undefined> {
): MaybePromise<number | bigint | undefined> {
const promisesOrNumbers = fn ? (this.map(fn as any) as R[] | Promise<R>[]) : (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;

0 comments on commit 2866b99

Please sign in to comment.