Skip to content

Instantly share code, notes, and snippets.

@KrofDrakula
Created December 14, 2022 15:00
Show Gist options
  • Save KrofDrakula/3c4d40e8aacf64602f6a6fe9e96f300b to your computer and use it in GitHub Desktop.
Save KrofDrakula/3c4d40e8aacf64602f6a6fe9e96f300b to your computer and use it in GitHub Desktop.
`Map` and `Set` functional method extensions for convenience
interface Set<T> {
map: <V>(
this: Set<T>,
mapper: (this: Set<T>, value: T, index: number, set: Set<T>) => V
) => Set<V>;
filter: (
this: Set<T>,
predicate: (this: Set<T>, value: T, index: number, set: Set<T>) => boolean
) => Set<T>;
reduce: <V>(
this: Set<T>,
reducer: (accumulator: V, next: T) => V,
initial: V
) => V;
}
interface Map<K, V> {
map: <U>(
this: Map<K, V>,
mapper: (this: Map<K, V>, value: V, key: K, map: Map<K, V>) => U
) => Map<K, U>;
filter: (
this: Map<K, V>,
predicate: (this: Map<K, V>, value: V, key: K, map: Map<K, V>) => boolean
) => Map<K, V>;
reduce: <T>(
this: Map<K, V>,
reducer: (accumulator: T, nextValue: V, nextKey: K) => T,
initial: T
) => T;
}
Set.prototype.map = function <V>(mapper) {
const result = new Set<V>();
let i = 0;
for (const item of this) {
result.add(mapper.call(this, item, i++, this));
}
return result;
};
Set.prototype.filter = function (predicate) {
type T = typeof this extends Set<infer T> ? T : never;
const result = new Set<T>();
let i = 0;
for (const item of this)
if (predicate.call(this, item, i++, this)) result.add(item);
return result;
};
Set.prototype.reduce = function (reducer, initial) {
let accumulator = initial;
let i = 0;
for (const value of this)
accumulator = reducer.call(this, accumulator, value, i++, this);
return accumulator;
};
Map.prototype.map = function <T>(mapper) {
type K = typeof this extends Map<infer A, any> ? A : never;
const result = new Map<K, T>();
for (const [key, value] of this.entries())
result.set(key, mapper.call(this, value, key, this));
return result;
};
Map.prototype.filter = function (predicate) {
type K = typeof this extends Map<infer A, any> ? A : never;
type V = typeof this extends Map<any, infer A> ? A : never;
const result = new Map<K, V>();
for (const [key, value] of this.entries())
if (predicate.call(this, value, key, this)) result.set(key, value);
return result;
};
Map.prototype.reduce = function (reducer, initial) {
let accumulator = initial;
for (const [key, value] of this.entries())
accumulator = reducer.call(this, accumulator, value, key, this);
return accumulator;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment