Last active
April 4, 2017 05:01
-
-
Save typoerr/ef6ad7ae6685e5863513e81bc630a924 to your computer and use it in GitHub Desktop.
immutable entries collection helpers
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 Entries<K, V> = Entry<K, V>[]; | |
export type Entry<K, V> = [K, V]; | |
export type Iteratee<K, V, R> = (v: V, k: K, index: number, src: Entries<K, V>) => R; | |
namespace util { | |
export function existy(v: any) { | |
return !(v === null || v === undefined); | |
} | |
export function includes<T>(src: T[], target: T) { | |
return src.indexOf(target) >= 0; | |
} | |
export function makeIteratee<K, V, R>(fn: Iteratee<K, V, R>, context: object | undefined) { | |
return function (e: Entry<K, V>, i: number, co: Entries<K, V>): R { | |
return fn.call(context, e[1], e[0], i, co); | |
}; | |
} | |
} | |
export function has<K, V>(co: Entries<K, V>, key: K) { | |
return util.existy(get(co, key)); | |
} | |
export function get<K, V>(co: Entries<K, V>, key: K) { | |
const results = co.find(([k]) => k === key); | |
return util.existy(results) ? results : undefined; | |
} | |
export function set<K, V>(co: Entries<K, V>, key: K, value: V) { | |
return merge(co, [[key, value]]); | |
} | |
export function merge<K, V>(co: Entries<K, V>, src: Entries<K, V>) { | |
const map = new Map(co); | |
src.forEach(([k, v]) => map.set(k, v)); | |
return Array.from(map); | |
} | |
export function pick<K, V>(co: Entries<K, V>, keys: K[]) { | |
return filter(co, (_, k) => util.includes(keys, k)); | |
} | |
export function remove<K, V>(co: Entries<K, V>, key: K) { | |
return filter(co, (_, k) => k !== key); | |
} | |
export function keys<K, V>(co: Entries<K, V>) { | |
return co.map(([k]) => k); | |
} | |
export function values<K, V>(co: Entries<K, V>) { | |
return co.map(([_, v]) => v); | |
} | |
export function first<K, V>(co: Entries<K, V>): Entry<K, V> | undefined { | |
return co.length > 0 ? [...co][0] : undefined; | |
} | |
export function last<K, V>(co: Entries<K, V>): Entry<K, V> | undefined { | |
return [...co].reverse()[0]; | |
} | |
export function forEach<K, V>(co: Entries<K, V>, callback: Iteratee<K, V, void>, context?: object) { | |
return co.forEach(util.makeIteratee(callback, context)); | |
} | |
export function filter<K, V>(co: Entries<K, V>, callback: Iteratee<K, V, boolean>, context?: object) { | |
return co.filter(util.makeIteratee(callback, context)); | |
} | |
export function map<K, V, R>(co: Entries<K, V>, callback: Iteratee<K, V, R>, context?: object): R[] { | |
return co.map(util.makeIteratee(callback, context)); | |
} | |
export function reduce<K, V, T>(co: Entries<K, V>, callback: _reduce.callback<K, V, T>, init: T): T { | |
return co.reduce(_reduce.makeReducer(callback), init); | |
} | |
export namespace _reduce { | |
export type callback<K, V, T> = (acc: T, value: V, key: K, index: number, src: Entries<K, V>) => T; | |
export function makeReducer<K, V, T>(callback: _reduce.callback<K, V, T>) { | |
return function (acc: T, kv: Entry<K, V>, i: number, src: Entries<K, V>) { | |
return callback.call(null, acc, kv[1], kv[0], i, src); | |
}; | |
} | |
} | |
export function toEntries<T, K extends keyof T, V extends T[K]>(src: T): Entries<string, V> { | |
return Object.keys(src).map((k: K) => [k, src[k]]) as Entries<K, V>; | |
} | |
export function toHash<K, V>(co: Entries<K, V>) { | |
return co.reduce((acc, [k, v]) => { | |
acc[k + ""] = v; | |
return acc; | |
}, {} as { [k: string]: V }); | |
} | |
export function toMap<K, V>(col: Entries<K, V>) { | |
return new Map(col); | |
} | |
export function fromMap<K, V>(map: Map<K, V>) { | |
return Array.from(map); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment