Skip to content

Instantly share code, notes, and snippets.

@tomcant
Created April 16, 2022 11:42
Show Gist options
  • Save tomcant/4a5b9dc2adddcb6d8bfb084c197c8e81 to your computer and use it in GitHub Desktop.
Save tomcant/4a5b9dc2adddcb6d8bfb084c197c8e81 to your computer and use it in GitHub Desktop.
Use objects as TypeScript map keys with this CompoundMap class
export default class CompoundMap<K, V> implements Map<K, V> {
private readonly items: Map<string, { key: K; value: V }>;
constructor(entries: [K, V][] = []) {
this.items = new Map(
entries.map(([key, value]) => [this.toKey(key), { key, value }])
);
}
clear(): void {
this.items.clear();
}
delete(key: K): boolean {
return this.items.delete(this.toKey(key));
}
get(key: K): V | undefined {
return this.items.get(this.toKey(key))?.value;
}
has(key: K): boolean {
return this.items.has(this.toKey(key));
}
set(key: K, value: V): this {
this.items.set(this.toKey(key), { key, value });
return this;
}
*[Symbol.iterator](): IterableIterator<[K, V]> {
for (const [, { key, value }] of this.items) {
yield [key, value];
}
}
*entries(): IterableIterator<[K, V]> {
yield* this[Symbol.iterator]();
}
*keys(): IterableIterator<K> {
for (const [, { key }] of this.items) {
yield key;
}
}
*values(): IterableIterator<V> {
for (const [, { value }] of this.items) {
yield value;
}
}
forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void {
for (const [, { key, value }] of this.items) {
callbackfn.call(thisArg, value, key, this);
}
}
get size(): number {
return this.items.size;
}
get [Symbol.toStringTag](): string {
return this.constructor.name;
}
private toKey(key: K): string {
return JSON.stringify(key);
}
}
import CompoundMap from "./CompoundMap";
type Point = {
x: number;
y: number;
};
const points = new CompoundMap<Point, string>();
points.set({ x: 0, y: 0 }, "The origin");
console.log(points.get({ x: 0, y: 0 })); // The origin
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment