space-lift
Version:
TypeScript Array, Object, Map, Set, Union, Enum utils
102 lines (101 loc) • 2.89 kB
JavaScript
import { update } from './immupdate';
/** A Map wrapper providing extra functionalities and more chaining opportunities */
export class MapWrapper {
constructor(_value) {
this._value = _value;
this._isLiftWrapper = true;
/**
* Pipes this Map with an arbitrary transformation function.
*/
this.pipe = pipe;
}
value() {
return this._value;
}
_clone() {
return new Map(this._value);
}
/**
* Sets a new key/value.
*/
set(key, value) {
return new MapWrapper(this._clone().set(key, value));
}
/**
* Deletes a key/value.
*/
delete(key) {
const result = this._clone();
result.delete(key);
return new MapWrapper(result);
}
/**
* Maps this Map's keys and values, unless void or undefined is returned, in which case the entry is filtered.
* This is effectively a filter + map combined in one.
*/
collect(iterator) {
const result = new Map();
this._value.forEach((value, key) => {
const res = iterator(key, value);
if (res !== undefined)
result.set(res[0], res[1]);
});
return new MapWrapper(result);
}
filter(predicate) {
return this.collect((key, value) => (predicate(key, value) ? [key, value] : undefined));
}
/**
* Returns the first element in this Map or undefined.
*/
first() {
return Array.from(this._value.values())[0];
}
/**
* Returns the last element in this Map or undefined.
*/
last() {
return Array.from(this._value.values()).pop();
}
/**
* Maps this map's values.
*/
mapValues(mapFunction) {
return this.collect((key, value) => [key, mapFunction(value)]);
}
/**
* If this key is missing, set a default value.
*/
setDefaultValue(key, value) {
if (this._value.has(key))
return this;
return this.set(key, value);
}
/**
* If the key is found, run the drafted value through an update function.
* For primitives, the update function must return a new value whereas for objects, the drafted value can be modified directly.
*/
updateValue(key, updater) {
return this.pipe(m => update(m, draft => draft.updateValue(key, updater)));
}
/**
* Transforms this Map into an Array of [key, value] tuples.
*/
toArray() {
return this.pipe(m => [...m]);
}
/**
* Transforms this Map into an Object.
* Only available if this Map's keys are a subtype of string or number.
*/
toObject() {
return this.pipe(m => [...m].reduce((obj, [key, val]) => {
obj[key] = val;
return obj;
}, {}));
}
}
let pipe;
export function setMapPipe(_pipe) {
pipe = _pipe;
}