打字稿中的ES6地图


173

我正在打字稿中创建一个具有如下属性的类,该类是ES6(ECMAscript 2016)地图:

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

如何在打字稿中声明ES6 Map类型?

Answers:


233

编辑(2019年6月5日):尽管“ TypeScript Map本机支持” 的想法仍然成立,但是自2.1版TypeScript支持称为的东西以来Record

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

不幸的是,第一个通用参数(键类型)仍然没有被完全尊重:即使使用string类型,像peopleA[0](a number)之类的东西仍然有效。


编辑(2016年4月25日):以下答案是旧的,不应视为最佳答案。TypeScript现在确实“本地”支持Maps,因此它仅允许在输出为ES6时使用ES6 Maps。对于ES5,它不提供polyfill;您需要自己嵌入它们。

有关更多信息,请参考下面的穆罕默德·黑格兹(Mohamed hegazy)的答案,以获取更现代的答案,甚至可参考此reddit评论中的简短版本。


从1.5.0 beta版开始,TypeScript尚不支持Maps。它也不是路线图的一部分。

当前的最佳解决方案是具有键和值的类型的对象(有时称为哈希图)。对于键类型为string,值类型为的对象number

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

但是,请注意以下几点:

  1. 键只能是类型stringnumber
  2. 实际上,将什么用作键类型并不重要,因为数字/字符串仍然可以互换接受(仅强制执行值)。

通过上面的示例:

// 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

3
然后如何迭代地图中的属性?当我执行arr.values()时,我得到“属性'values'在类型上不存在...”
Vern Jensen

values()我会for (var key in arr) ... arr[key]或不会一样for...of。其他解决方案(当今越来越现实,并且在很多事情上还会出现一段时间)是使用corejs
zeh 2015年

实际上,当我将任何键用作以此方式声明的地图上的属性时,我会得到“类型上不存在属性'whatever'”
rakslice

我正在使用map类来构建一个,但是即使我map Map<string,string>=new Map<string,string>()map.set(something) 遇到异常时也这样做map is undefined,还有另一种初始化它的方法吗?
mautrok

1
当靶向ES5,即使polyfills,您不能使用某些功能-见github.com/Microsoft/TypeScript/issues/6842
Ondra参观Žižka

128

看到评论:https : //github.com/Microsoft/TypeScript/issues/3069#issuecomment-99964139

TypeScript没有内置的pollyfills。您可以自行决定使用哪个填埋场。您可以使用 es6Collectiones6-shimscorejs ..etc之类的东西。Typescript编译器仅需要声明要使用的ES6结构。您可以在此lib文件中找到它们。

这是相关的部分:

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;

3
当靶向ES5,即使polyfills,您不能使用某些功能-见github.com/Microsoft/TypeScript/issues/6842
Ondra参观Žižka


30

是,现在可以在打字稿中使用Map。.如果您查看lib.es6.d.ts,将看到以下界面:

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;} 

用作字符串,对象对的字典非常有用。唯一的烦恼是,如果使用Map.get(key)在其他地方使用它分配值,类似Code的IDE会给您带来可能无法定义的问题。使用is-defined check创建一个变量..只需强制转换类型(假设您确定地图具有键值对)

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



4

不知道这是否是官方的,但这在打字稿2.7.1中对我有用:

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

简单来说 Map<keyType, valueType>


3

使用lib config选项,您可以将Map挑选到您的项目中。只需添加es2015.collection到您的lib部分。如果没有lib config,请添加一个默认值并添加es2015.collection

因此,当您有目标:es5时,将tsconfig.json更改为:

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


0

"target": "ESNEXT"属性添加到tsconfig.json文件。

{
    "compilerOptions": {
        "target": "ESNEXT" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.