Edit: I've updated the code and uploaded a gist that will work in the TS playground - the gist will compile with Typescript 3.0's strictest settings (at least all the strict settings available to the playground)1.
export interface Dictionary<K, V> {
getKeys(): K[];
getValues(): V[];
get(key: K): V;V | null; // the key might not exist
put(key: K, val: V): void; // or boolean?
}
export class JSDictionary<K extends string, V> implements Dictionary<K, V> {
private internalDict: Partial<Record<K,{ V>>;[key in K]?: V };
constructor() {
this.internalDict = {};
}
public getKeys(): K[] {
let keys: K[] = [];
for(let key in this.internalDict) {
keys.push(key);
}
return keys;
}
public// getValuesType predicate to ensure v exists
private exists(v: V | undefined): V[]v is V {
return v != null && typeof v !== "undefined";
}
public getValues() {
let vals: V[] = [];
for(let key in this.internalDict) {
valslet v = this.pushinternalDict[key];
if(this.internalDict[key]exists(v)) {
vals.push(v);
}
}
return vals;
}
public get(key: K): V {
returnlet v = this.internalDict[key];
return this.exists(v)
? v
: null;
}
public put(key: K, val: V): void {
this.internalDict[key] = val;
}
}
type myKeys = 'FOX' | 'CAT' | 'DOG';
interface Animal {
species: string;
name: string;
weight: number;
}
// A dictionary that hols one fox/cat/dog.
let myAnimalPen = new JSDictionary<myKeys, Animal>();
myAnimalPen.put('FOX', { name: 'Foxworth', species: 'Fox', weight: 40 });
// a dictionary that takes any string and maps it to a number
let idDict = new JSDictionary<string, number>();
idDict.put('somehas', 1204);
idDict.put('yeahaasd', 3306);
let yeaID = idDict.get('yeahaasd'); // yeaID is a number | null type
let myFox = myAnimalPen.get('FOX'); // myFox is an Animal | null type