TypeScript Dictionary class
Edit: I've updated the code and uploaded a gist that will work in the TS playground - the gist will compile with Typescript 3.1.

The primary benefit of Typescript is to provide types for Javascript. And since Typescript provides Generics - I don't think your implementation of a Dictionary provides any benefit over a plain javascript object.

In fact, as you noted in the comments, JS Objects (ie TS object) are dictionaries. You just need to provide types around them for your dictionary. (btw - I also come from a C# background, but I've also come to love the underlying functional nature of JS that TS lets us type).

Here's a code sample of the direction I would expect a Dictionary.ts class to have in a code base I work in. Now that we have Mapped Types, we can generalize dictionaries better.

export interface Dictionary&lt;K, V&gt; {
  getKeys(): K[];
  getValues(): V[];
  get(key: K): V | null; // the key might not exist
  put(key: K, val: V): void; // or boolean?
}


export class JSDictionary&lt;K extends string, V&gt; implements Dictionary&lt;K, V&gt; {

  private internalDict: { [key in K]?: V };

  constructor() {
    this.internalDict = {};
  }

  public getKeys() {
    let keys: K[] = [];
    for(let key in this.internalDict) {
      keys.push(key);
    }

    return keys;
  }

  // Type predicate to ensure v exists
  private exists(v: V | undefined): v is V {
    return v != null &amp;&amp; typeof v !== "undefined";
  }

  public getValues() {
    let vals: V[] = [];

    for(let key in this.internalDict) {
      let v = this.internalDict[key];
      if(this.exists(v)) {
        vals.push(v);
      }
    }

    return vals;
  }

  public get(key: K) {
    let v = this.internalDict[key];
    return this.exists(v)
      ? v
      : null;
  }

  public put(key: K, val: V): void {
    this.internalDict[key] = val;
  }

}


Example Usage

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&lt;myKeys, Animal&gt;();

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&lt;string, number&gt;();
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


Major points:


Code to an interface as much as you can in typescript. Affords you flexibility
Generic types
Transparent use of Plain JS object as the underlying dictionary (JS Engines optimize this very use case!)
I removed overloaded constructors, but you could add that back in with the proper types and it will work as expected
Left out clone - pretty easy to implement though
No exception handling when get returns null, like your 'try*' functions. I actually like try functions like you have, so you could mostly copy/paste, although with the stricter typings sometimes that will be taken care of by the compiler for you.