nicksrandall
nicksrandall

Reputation: 3148

ES6 Map in Typescript

I'm creating a class in typescript that has a property that is an ES6 (ECMAscript 2016) Map like so:

class Item {
  configs: ????;
  constructor () {
    this.configs = new Map();
  }
}

How do I declare an ES6 Map type in typescript?

Upvotes: 306

Views: 798471

Answers (11)

Lenzman
Lenzman

Reputation: 1400

You can create a Map inside a Typescript class as follows

export class Shop {
  public locations: Map<number, string>;

  constructor() {
   // initialize an empty map
   this.locations= new Map<number,string>();
  }

   // get & set functions
   ........
}

Upvotes: 0

zeh
zeh

Reputation: 10659

EDIT (Jun 5 2019): While the idea that "TypeScript supports Map natively" is still true, since version 2.1 TypeScript supports something called Record.

type MyMapLikeType = Record<string, IPerson>;
const peopleA: MyMapLikeType = {
    "a": { name: "joe" },
    "b": { name: "bart" },
};

Unfortunately the first generic parameter (key type) is still not fully respected: even with a string type, something like peopleA[0] (a number) is still valid.


EDIT (Apr 25 2016): The answer below is old and should not be considered the best answer. TypeScript does support Maps "natively" now, so it simply allows ES6 Maps to be used when the output is ES6. For ES5, it does not provide polyfills; you need to embed them yourself.

For more information, refer to mohamed hegazy's answer below for a more modern answer, or even this reddit comment for a short version.


As of 1.5.0 beta, TypeScript does not yet support Maps. It is not yet part of the roadmap, either.

The current best solution is an object with typed key and value (sometimes called a hashmap). For an object with keys of type string, and values of type number:

var arr : { [key:string]:number; } = {};

Some caveats, however:

  1. keys can only be of type string or number
  2. It actually doesn't matter what you use as the key type, since numbers/strings are still accepted interchangeably (only the value is enforced).

With the above example:

// OK:
arr["name"] = 1; // String key is fine
arr[0] = 0; // Number key is fine too

// Not OK:
arr[{ a: "a" }] = 2; // Invalid key
arr[3] = "name"; // Invalid value

Upvotes: 387

HolgerJeromin
HolgerJeromin

Reputation: 2462

With the lib config option your are able to cherry pick Map into your project. Just add es2015.collection to your lib section. When you have no lib config add one with the defaults and add es2015.collection.

So when you have target: es5, change tsconfig.json to:

"target": "es5",
"lib": [ "dom", "es5", "scripthost", "es2015.collection" ],

Upvotes: 4

nphias
nphias

Reputation: 619

Yes Map is now available in typescript.. if you look in lib.es6.d.ts, you will see the interface:

interface Map<K, V> {
  clear(): void;
  delete(key: K): boolean;
  forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void,thisArg?: any): void;
  get(key: K): V | undefined;
  has(key: K): boolean;
  set(key: K, value: V): this;
  readonly size: number;} 

Its great to use as a dictionary of string,object pairs.. the only annoyance is that if you are using it to assign values elsewhere with Map.get(key) the IDE like Code gives you problems about being possible undefined.. rather than creating a variable with an is-defined check .. simply cast the type (assuming you know for sure the map has the key-value pair)

class myclass {
   mymap:Map<string,object>
   ...
   mymap = new Map<string,object>()
   mymap.set("akey",AnObject)
   let objectref = <AnObject>mymap.get("akey")

Upvotes: 55

Jonas Tomanga
Jonas Tomanga

Reputation: 1108

Not sure if this is official but this worked for me in typescript 2.7.1:

class Item {
   configs: Map<string, string>;
   constructor () {
     this.configs = new Map();
   }
}

In simple Map<keyType, valueType>

Upvotes: 10

Yas
Yas

Reputation: 5471

Add "target": "ESNEXT" property to the tsconfig.json file.

{
    "compilerOptions": {
        "target": "ESNEXT" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
    }
}

Upvotes: 1

Arnaud
Arnaud

Reputation: 7439

Here is an example:

this.configs = new Map<string, string>();
this.configs.set("key", "value");

Demo

Upvotes: 109

Nikos
Nikos

Reputation: 7552

As a bare minimum:

tsconfig:

 "lib": [
      "es2015"
    ]

and install a polyfill such as https://github.com/zloirock/core-js if you want IE < 11 support: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

Upvotes: 12

mohamed hegazy
mohamed hegazy

Reputation: 9509

See comment in: https://github.com/Microsoft/TypeScript/issues/3069#issuecomment-99964139

TypeScript does not come with built in pollyfills. it is up to you to decide which pollyfill to use, if any. you can use something like es6Collection, es6-shims, corejs..etc. All the Typescript compiler needs is a declaration for the ES6 constructs you want to use. you can find them all in this lib file.

here is the relevant portion:

interface Map<K, V> {
    clear(): void;
    delete(key: K): boolean;
    entries(): IterableIterator<[K, V]>;
    forEach(callbackfn: (value: V, index: K, map: Map<K, V>) => void, thisArg?: any): void;
    get(key: K): V;
    has(key: K): boolean;
    keys(): IterableIterator<K>;
    set(key: K, value?: V): Map<K, V>;
    size: number;
    values(): IterableIterator<V>;
    [Symbol.iterator]():IterableIterator<[K,V]>;
    [Symbol.toStringTag]: string;
}

interface MapConstructor {
    new <K, V>(): Map<K, V>;
    new <K, V>(iterable: Iterable<[K, V]>): Map<K, V>;
    prototype: Map<any, any>;
}
declare var Map: MapConstructor;

Upvotes: 134

basarat
basarat

Reputation: 275917

How do I declare an ES6 Map type in typescript?

You need to target --module es6. This is misfortunate and you can raise your concern here : https://github.com/Microsoft/TypeScript/issues/2953#issuecomment-98514111

Upvotes: 14

Logan Tegman
Logan Tegman

Reputation: 847

Typescript does not yet support Map.

ES6 Compatibility Table

Upvotes: 2

Related Questions