Skip to content

Instantly share code, notes, and snippets.

@Voltra
Last active June 20, 2022 18:22
Show Gist options
  • Select an option

  • Save Voltra/9296201d307a4df11886f4ce86130741 to your computer and use it in GitHub Desktop.

Select an option

Save Voltra/9296201d307a4df11886f4ce86130741 to your computer and use it in GitHub Desktop.
JS extension methods
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