Skip to content

Instantly share code, notes, and snippets.

@rbuckton
Last active December 9, 2016 23:11
Show Gist options
  • Save rbuckton/06d2c79bea46778f9e8bbeca77292087 to your computer and use it in GitHub Desktop.
Save rbuckton/06d2c79bea46778f9e8bbeca77292087 to your computer and use it in GitHub Desktop.
shim for Map<T> with keys/values/entries support
function shimMap() {
function createDictionaryObject<T>() {
const obj: MapLike<T> = Object.create(null); // tslint:disable-line:no-null-keyword
obj["__"] = undefined;
delete obj["__"];
return obj;
}
function getKey<T>(_data: MapLike<T>, key: string) {
return key;
}
function getValue<T>(data: MapLike<T>, key: string) {
return data[key];
}
function getEntry<T>(data: MapLike<T>, key: string) {
return [key, data[key]] as [string, T];
}
class MapIterator<T, U extends (string | T | [string, T])> {
private data: MapLike<T>;
private keys: string[];
private index: number = 0;
private selector: (data: MapLike<T>, key: string) => U;
constructor(data: MapLike<T>, selector: (data: MapLike<T>, key: string) => U) {
this.data = data;
this.selector = selector;
this.keys = Object.keys(data);
}
public next(): ({ value: U, done: false } | { value: never, done: true }) {
const index = this.index;
if (index < this.keys.length) {
this.index++;
return { value: this.selector(this.data, this.keys[index]), done: false };
}
return { value: <never>undefined, done: true };
}
}
return class Map<T> {
private data: MapLike<T> = createDictionaryObject<T>();
public size = 0;
public has(key: string) {
return key in this.data; // tslint:disable-line:no-in-operator
}
public get(key: string) {
return this.data[key];
}
public set(key: string, value: T) {
if (!this.has(key)) {
this.size++;
}
this.data[key] = value;
return this;
}
public delete(key: string) {
if (this.has(key)) {
this.size--;
delete this.data[key];
return true;
}
return false;
}
public clear() {
this.data = createDictionaryObject<T>();
this.size = 0;
}
public keys() {
return new MapIterator(this.data, getKey);
}
public values() {
return new MapIterator(this.data, getValue);
}
public entries() {
return new MapIterator(this.data, getEntry);
}
public forEach(callback: (value: T, key: string) => void) {
for (const key in this.data) {
callback(this.data[key], key);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment