diff --git a/src/array.test.ts b/src/array.test.ts index 9bf5af5..706e25d 100644 --- a/src/array.test.ts +++ b/src/array.test.ts @@ -190,4 +190,42 @@ describe("array", () => { ).toThrow(); }); }); + + describe("asyncSome", () => { + it("returns true if any element matches async predicate (even number)", async () => { + // given an array of even and odd numbers + const a = [1, 2, 3, 4, 5]; + // when we call asyncSome with an async predicate that checks for even numbers + const result = await a.asyncSome((el) => Promise.resolve(el % 2 === 0)); + // then expect asyncSome to return true + expect(result).toBe(true); + }); + + it("returns true if any element matches sync/async predicate (1 or even number)", async () => { + // given an array of even and odd numbers which includes 1 + const a = [1, 2, 3, 4, 5]; + // when we call asyncSome with a sync/async predicate that checks for 1 or even numbers + const result = await a.asyncSome((el) => el === 1 || Promise.resolve(el % 2 === 0)); + // then expect asyncSome to return true + expect(result).toBe(true); + }); + + it("returns false if no elements match async predicate (even number)", async () => { + // given an array of odd numbers + const a = [1, 3, 5]; + // when we call asyncSome with an async predicate that checks for even numbers + const result = await a.asyncSome((el) => Promise.resolve(el % 2 === 0)); + // then expect asyncSome to return false + expect(result).toBe(false); + }); + + it("returns false if the array is empty", async () => { + // given an empty array + const a: number[] = []; + // when we call asyncSome with an async predicate that checks for even numbers + const result = await a.asyncSome((el) => Promise.resolve(el % 2 === 0)); + // then expect asyncSome to return false + expect(result).toBe(false); + }); + }); }); diff --git a/src/array.ts b/src/array.ts index a60578d..006e40c 100644 --- a/src/array.ts +++ b/src/array.ts @@ -29,6 +29,7 @@ declare global { each(f: (el: T, index: number, array: T[]) => any): T[]; /** Helper for filtering arrays on async predicates. */ asyncFilter(predicate: (v: T) => Promise): Promise>; + asyncSome(predicate: (v: T) => boolean | Promise): Promise; asyncMap(f: (el: T, index: number, array: T[]) => Promise): Promise; asyncForEach(f: (el: T, index: number, array: T[]) => Promise): Promise; sum(this: Array): number; @@ -97,6 +98,7 @@ declare global { each(f: (el: T, index: number, array: T[]) => any): T[]; /** Helper for filtering arrays on async predicates. */ asyncFilter(predicate: (v: T) => Promise): Promise>; + asyncSome(predicate: (v: T) => boolean | Promise): Promise; asyncMap(f: (el: T, index: number, array: T[]) => Promise): Promise; asyncForEach(f: (el: T, index: number, array: T[]) => Promise): Promise; sum(this: ReadonlyArray): number; @@ -219,6 +221,29 @@ Array.prototype.asyncFilter = async function ( return this.filter((_v, index) => results[index]); }; +Array.prototype.asyncSome = async function ( + this: Array, + predicate: (v: T) => boolean | Promise, +): Promise { + const asyncResults: Promise[] = []; + for (const el of this) { + const result = predicate(el); + if (typeof result === "boolean") { + if (result) { + return true; + } + } else { + asyncResults.push(result); + } + } + for (const result of asyncResults) { + if (await result) { + return true; + } + } + return false; +}; + Array.prototype.asyncMap = async function ( this: Array, f: (el: T, index: number, array: T[]) => Promise,