Last active
June 20, 2022 18:22
-
-
Save Voltra/9296201d307a4df11886f4ce86130741 to your computer and use it in GitHub Desktop.
JS extension methods
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| export type ArrayPartitionResult<T> = [left: T[], right: T[]]; | |
| const partitionArr = function<T>(this: T[], predicate: (item: T, i: number, arr: T[]) => boolean): ArrayPartitionResult<T> { | |
| return this.reduce((partitions: ArrayPartitionResult<T>, item: T, i: number): ArrayPartitionResult<T> => { | |
| const partitionIndex = predicate(item, i, this) ? 0 : 1; | |
| partitions[partitionIndex].push(item); | |
| return partitions; | |
| }, [[], []] as ArrayPartitionResult<T>); | |
| }; | |
| const asyncMap = function<T, U>(this: T[], asyncMapper: (item: T, i: number, arr: T[]) => Promise<U>): Promise<U[]> { | |
| return Promise.all( | |
| this.map(asyncMapper) | |
| ); | |
| }; | |
| const asyncForEach = async function<T>(this: T[], callback: (item: T, i: number, arr: T[]) => Promise<void>): Promise<void> { | |
| await asyncMap<T, void>.call(this, callback); | |
| } | |
| const asyncFilter = async function<T>(this: T[], asyncPredicate: (item: T, i: number, arr: T[]) => Promise<boolean>): Promise<T[]> { | |
| const ret = [] as T[]; | |
| await asyncForEach<T>.call(this, async (item: T, i: number, arr: T[]) => { | |
| const satisfies = await asyncPredicate(item, i, arr); | |
| if (satisfies) { | |
| ret.push(item); | |
| } | |
| }); | |
| return ret; | |
| }; | |
| const asyncReduce = async function<T, Acc>(this: T[], asyncReducer: (acc: Acc, item: T, i: number, arr: T[]) => Promise<Acc>, initialAcc: Acc): Promise<Acc> { | |
| let ret: Acc = initialAcc; | |
| await asyncForEach<T>.call(this, async (item: T, i: number, arr: T[]) => { | |
| ret = await asyncReducer(ret, item, i, arr); | |
| }); | |
| return ret; | |
| } | |
| const asyncFind = async function<T>(this: T[], asyncPredicate: (item: T, i: number, arr: T[]) => Promise<boolean>): Promise<T|undefined> { | |
| for (const i in this) { | |
| const item = this[i]; | |
| const didFind = await asyncPredicate(item, i as unknown as number, this); | |
| if (didFind) { | |
| return item; | |
| } | |
| } | |
| return undefined; | |
| } | |
| const asyncFindOr = async function<T>(this: T[], asyncPredicate: (item: T, i: number, arr: T[]) => Promise<boolean>, defaultValue: T) { | |
| return (await asyncFind<T>.call(this, asyncPredicate)) ?? defaultValue; | |
| } | |
| const asyncFindIndex = async function<T>(this: T[], asyncPredicate: (item: T, i: number, arr: T[]) => Promise<boolean>): Promise<number> { | |
| for (const i in this) { | |
| const index: number = i as unknown as number; | |
| const didFind = await asyncPredicate(this[i], index, this); | |
| if (didFind) { | |
| return index; | |
| } | |
| } | |
| return -1; | |
| } | |
| const asyncSome = async function<T>(this: T[], asyncPredicate: (item: T, i: number, arr: T[]) => Promise<boolean>): Promise<boolean> { | |
| for (const i in this) { | |
| const index: number = i as unknown as number; | |
| const satisfies = await asyncPredicate(this[i], index, this); | |
| if (satisfies) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| const asyncEvery = async function<T>(this: T[], asyncPredicate: (item: T, i: number, arr: T[]) => Promise<boolean>): Promise<boolean> { | |
| for (const i in this) { | |
| const index: number = i as unknown as number; | |
| const satisfies = await asyncPredicate(this[i], index, this); | |
| if (!satisfies) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| const asyncNone = async function<T>(this: T[], asyncPredicate: (item: T, i: number, arr: T[]) => Promise<boolean>): Promise<boolean> { | |
| return !(await asyncSome<T>.call(this, asyncPredicate)); | |
| } | |
| const asyncMapReduce = async function<T, U, Acc>( | |
| this: T[], | |
| asyncMapper: (item: T, i: number, arr: T[]) => Promise<U>, | |
| asyncReducer: (acc: Acc, item: U, origItem: T, i: number, arr: T[]) => Promise<Acc>, | |
| initialAcc: Acc | |
| ): Promise<Acc> { | |
| let ret: Acc = initialAcc; | |
| await asyncForEach<T>.call(this, async (item: T, i: number, arr: T[]) => { | |
| const mappedItem = await asyncMapper(item, i, arr); | |
| ret = await asyncReducer(ret, mappedItem, item, i, arr); | |
| }); | |
| return ret; | |
| } | |
| Object.assign(Array.prototype, { | |
| partition: partitionArr, | |
| asyncMap, | |
| asyncForEach, | |
| asyncFilter, | |
| asyncReduce, | |
| asyncFind, | |
| asyncFindOr, | |
| asyncFindIndex, | |
| asyncSome, | |
| asyncEvery, | |
| asyncNone, | |
| asyncMapReduce, | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment