Карта ES6 в Typescript


174

Я создаю класс в машинописи, у которого есть свойство, которое является картой ES6 (ECMAscript 2016) следующим образом:

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

Как объявить тип карты ES6 в машинописи?

Ответы:


234

РЕДАКТИРОВАТЬ (5 июня 2019 г.): Хотя идея о том, что «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) все еще допустимо.


РЕДАКТИРОВАТЬ (25 апреля 2016 г.): приведенный ниже ответ является старым и не должен рассматриваться как лучший ответ. TypeScript теперь поддерживает «изначально» Карты, поэтому он просто позволяет использовать Карты ES6, когда выводом является ES6. Для ES5 он не предоставляет полифилы; Вы должны вставить их сами.

Для получения дополнительной информации, обратитесь к ответу Мохамеда Хегази ниже для более современного ответа, или даже к этому комментарию reddit для короткой версии.


Начиная с бета-версии 1.5.0, TypeScript еще не поддерживает Карты . Это еще не часть дорожной карты .

В настоящее время лучшим решением является объект с типизированным ключом и значением (иногда называемый hashmap). Для объекта с ключами типа stringи значениями типа number:

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

Некоторые предостережения, однако:

  1. ключи могут быть только типа stringилиnumber
  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(), как я бы сделал for (var key in arr) ... arr[key]или for...of. Другое решение (которое становится все более и более реалистичным в настоящее время и будет на какое-то время для многих вещей) - это использовать corejs .
Zeh

Фактически, когда я использую любой ключ в качестве свойства на объявленной таким образом карте, я получаю «Свойство« что бы то ни было »для типа»
rakslice

Я использую класс карты построить один, но даже если я , map Map<string,string>=new Map<string,string>()когда я делаю map.set(something) я получаю исключение map is undefined, есть другой способ , чтобы инициализировать его?
Маутрок

1
Ориентируясь на ES5, даже с полифиллами, вы не можете использовать определенные функции - см. Github.com/Microsoft/TypeScript/issues/6842
Ондра Жижка

128

См. Комментарий в: https://github.com/Microsoft/TypeScript/issues/3069#issuecomment-99964139

TypeScript не поставляется со встроенными pollyfills. Вам решать, какой pollyfill использовать, если таковые имеются. Вы можете использовать что-то вроде es6Collection , es6- shims , corejs .. и т. д. Все, что нужно компилятору 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, даже с полифиллами, вы не можете использовать определенные функции - см. Github.com/Microsoft/TypeScript/issues/6842
Ондра Жижка


30

Да, карта теперь доступна для машинописного текста. Если вы посмотрите в 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 (ключ), IDE, такой как Code, создаст вам проблемы с возможностью быть неопределенной .., а не создание переменной с определенной проверкой. просто приведите тип (при условии, что вы точно знаете, что на карте есть пара ключ-значение)

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, добавьте ее со значениями по умолчанию и добавьте es2015.collection.

Поэтому, когда у вас есть target: 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'. */
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.