From 47342c04cc9f58daebcee8b93ecc547315b4b32a Mon Sep 17 00:00:00 2001 From: Arvin Siva Date: Tue, 30 Jan 2024 13:19:44 -0500 Subject: [PATCH] feat: add asyncSome to array --- src/array.test.ts | 30 ++++++++++++++++++++++++++++++ src/array.ts | 25 +++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/array.test.ts b/src/array.test.ts index 9bf5af5..980cc6b 100644 --- a/src/array.test.ts +++ b/src/array.test.ts @@ -190,4 +190,34 @@ 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]; + // then expect asyncSome to return true + expect(await a.asyncSome((el) => Promise.resolve(el % 2 === 0))).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]; + // then expect asyncSome to return true + expect(await a.asyncSome((el) => el === 1 || Promise.resolve(el % 2 === 0))).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]; + // then expect asyncSome to return false + expect(await a.asyncSome((el) => Promise.resolve(el % 2 === 0))).toBe(false); + }); + + it("returns false if the array is empty", async () => { + // given an empty array + const a: number[] = []; + // then expect asyncSome to return false + expect(await a.asyncSome((el) => Promise.resolve(el % 2 === 0))).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,