Карта ES6 в Typescript


173

Я створюю клас у машинописі, у якого є властивість, яка є ES6 (ECMAscript 2016):

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

Як я можу оголосити тип ES6 Map у машинописі?

Відповіді:


233

EDIT (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) все ще діє.


EDIT (25 квітня 2016 р.): Наведена нижче відповідь стара, і її не слід вважати найкращою відповіддю. В даний час TypeScript підтримує Карти "на самому", тому він просто дозволяє використовувати карти ES6, коли вихідним є ES6. Для ES5 він не забезпечує поліфілів; їх потрібно вставити самостійно.

Для отримання додаткової інформації, зверніться до відповіді мохамеда гегази нижче, щоб отримати більш сучасну відповідь, або навіть цей коментар для редагування для короткої версії.


Станом на 1.5.0 бета-версії, TypeScript ще не підтримує Карти . Це ще не є частиною дорожньої карти .

Поточне найкраще рішення - це об'єкт із набраним ключем та значенням (іноді його називають хешмапом). Для об'єкта з ключами типу 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 ​​(), я отримую "Значення" Властивості "не існують для типу ..."
Vern Jensen

Не те саме 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, чи є інший спосіб його ініціалізувати?
mautrok

1
Орієнтуючись на ES5, навіть із поліфазовами, ви не можете використовувати певні функції - див. Github.com/Microsoft/TypeScript/isissue/6842
Žižka

128

Дивіться коментар у: https://github.com/Microsoft/TypeScript/isissue/3069#issuecomment-99964139

TypeScript не поставляється із вбудованими в поліліфлі. вирішувати, який поліліф використовувати, якщо такий є, вирішувати саме вам. ви можете використовувати щось на зразок es6Collection , es6-shims , corejs ..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, навіть із поліфазовами, ви не можете використовувати певні функції - див. 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

Завдяки опції config lib ви зможете вишнево вибрати Map у свій проект. Просто додайте es2015.collectionдо розділу ліб. Якщо у вас немає конфігурації 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.