Created
October 27, 2020 02:39
-
-
Save rpggio/b8fa9f28fb16e9e2c9bb67c5dce1a262 to your computer and use it in GitHub Desktop.
Generic Map with complex key, in TypeScript
This file contains 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 function ComplexKeyedMap<K, V>( | |
formatter: StringFormatter<K>, | |
entries?: readonly (readonly [K, V])[] | null | |
): Map<K, V> { | |
const map = new Map<string, V>( | |
entries?.map(([k, v]) => [formatter.asString(k), v]) | |
) | |
function* getEntries() { | |
for (const [strKey, value] of map) { | |
yield [formatter.fromString(strKey), value] as [K, V] | |
} | |
} | |
const typedMap: Map<K, V> = { | |
clear: map.clear, | |
delete(key: K) { | |
return map.delete(formatter.asString(key)) | |
}, | |
forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any) { | |
map.forEach((value, key) => | |
callbackfn(value, formatter.fromString(key), typedMap), thisArg) | |
}, | |
get(key: K) { | |
return map.get(formatter.asString(key)) | |
}, | |
has(key: K) { | |
return map.has(formatter.asString(key)) | |
}, | |
set(key: K, value: V) { | |
map.set(formatter.asString(key), value) | |
return typedMap | |
}, | |
get size() { | |
return map.size | |
}, | |
[Symbol.iterator]: getEntries, | |
entries: getEntries, | |
*keys() { | |
for (const [strKey] of map) { | |
yield formatter.fromString(strKey) | |
} | |
}, | |
*values() { | |
for (const [, value] of map) { | |
yield value | |
} | |
}, | |
[Symbol.toStringTag]: map[Symbol.toStringTag] | |
} | |
return typedMap | |
} | |
export type StringFormatter<T> = { | |
asString: (t: T) => string, | |
fromString: (value: string) => T | |
} |
This file contains 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
import { ComplexKeyedMap, StringFormatter } from './complexKeyedMap' | |
type Point = [number, number] | |
const nullPoint: Point = [NaN, NaN] | |
export function PointMap<V>(entries?: readonly (readonly [Point, V])[] | null) { | |
return ComplexKeyedMap(keyFormatter, entries) | |
} | |
const keyFormatter: StringFormatter<Point> = { | |
asString(point: Point) { | |
return point.map(paddedUnit).join(',') | |
}, | |
fromString(literal: string): Point { | |
if (!literal) { | |
return nullPoint | |
} | |
const parts = literal.split(',') | |
if (parts.length !== 2) { | |
return nullPoint | |
} | |
return parts.map(it => Number(it)) as Point | |
} | |
} | |
function paddedUnit(unit: number) { | |
return unit.toString().padStart(5) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment