Mapa ES6 na maszynie


173

Tworzę klasę w maszynie, która ma właściwość, która jest mapą ES6 (ECMAscript 2016) w następujący sposób:

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

Jak zadeklarować typ mapy ES6 w maszynie?

Odpowiedzi:


233

EDYCJA (5 czerwca 2019 r.): Chociaż idea, że ​​„TypeScript obsługuje Mapnatywnie”, jest nadal aktualna, ponieważ wersja 2.1 TypeScript obsługuje coś o nazwie Record.

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

Niestety, pierwszy parametr ogólny (typ klucza) nadal nie jest w pełni przestrzegany: nawet w przypadku stringtypu coś takiego jak peopleA[0](a number) jest nadal ważne.


EDYCJA (25 kwietnia 2016 r.): Poniższa odpowiedź jest stara i nie należy jej uważać za najlepszą. TypeScript obsługuje teraz mapy „natywnie”, więc po prostu umożliwia używanie map ES6, gdy wynik jest w formacie ES6. W przypadku ES5 nie zapewnia wypełniaczy; musisz je samodzielnie osadzić.

Aby uzyskać więcej informacji, zapoznaj się z odpowiedzią mohamed hegazy poniżej, aby uzyskać bardziej nowoczesną odpowiedź, lub nawet ten komentarz reddit dotyczący krótkiej wersji.


Od wersji beta 1.5.0 TypeScript nie obsługuje jeszcze Map . Nie jest to również jeszcze część planu działania .

Obecnie najlepszym rozwiązaniem jest obiekt z wpisanym kluczem i wartością (czasami nazywany hasmapą). Dla obiektu z kluczami typu stringi wartościami typu number:

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

Jednak pewne zastrzeżenia:

  1. klucze mogą być tylko typu stringlubnumber
  2. W rzeczywistości nie ma znaczenia, jaki typ klucza użyjesz, ponieważ liczby / ciągi są nadal akceptowane zamiennie (wymuszana jest tylko wartość).

W powyższym przykładzie:

// 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
Jak więc możesz iterować właściwości na mapie? Kiedy robię arr.values ​​(), otrzymuję komunikat „Wartości właściwości” nie istnieją w typie ... ”
Vern Jensen

Nie to samo values(), co zrobiłbym for (var key in arr) ... arr[key]lub for...of. Innym rozwiązaniem (które jest coraz bardziej realistyczne w dzisiejszych czasach i przez jakiś czas będzie dla wielu rzeczy) jest użycie corejs .
zeh

W rzeczywistości, kiedy wykorzystać dowolny klawisz jako własność na mapie zadeklarowane w ten sposób otrzymuję „Własność«cokolwiek»nie istnieje w rodzaju”
rakslice

Używam klasy map, aby ją zbudować, ale nawet jeśli to zrobię, map Map<string,string>=new Map<string,string>()gdy map.set(something) otrzymam wyjątek map is undefined, czy istnieje inny sposób jej zainicjowania?
mautrok

1
Wybierając ES5, nawet z polyfills, nie możesz używać niektórych funkcji - patrz github.com/Microsoft/TypeScript/issues/6842
Ondra Žižka

128

Zobacz komentarz w: https://github.com/Microsoft/TypeScript/issues/3069#issuecomment-99964139

TypeScript nie zawiera wbudowanych pollyfills. to Ty decydujesz, którego wypełnienia pollyfill użyć, jeśli w ogóle. możesz użyć czegoś takiego jak es6Collection , es6- shims , corejs ..etc. Wszystko, czego potrzebuje kompilator Typescript, to deklaracja konstrukcji ES6, której chcesz użyć. możesz znaleźć je wszystkie w tym pliku lib .

oto odpowiednia część:

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
Podczas kierowania na ES5, nawet z polyfills, nie możesz używać niektórych funkcji - patrz github.com/Microsoft/TypeScript/issues/6842
Ondra Žižka


30

Tak Mapa jest teraz dostępna w maszynie. Jeśli spojrzysz na lib.es6.d.ts, zobaczysz interfejs:

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

Świetnie nadaje się do wykorzystania jako słownika par ciągów i obiektów ... jedyną irytacją jest to, że jeśli używasz go do przypisywania wartości w innym miejscu za pomocą Map.get (klucz), IDE, takie jak Code, powoduje problemy z byciem niezdefiniowanym .. zamiast tworzenie zmiennej ze sprawdzeniem jest zdefiniowane .. po prostu rzutuj typ (zakładając, że wiesz na pewno, że mapa ma parę klucz-wartość)

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



4

Nie jestem pewien, czy to oficjalne, ale zadziałało to dla mnie w maszynie 2.7.1:

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

W prosty sposób Map<keyType, valueType>


3

Dzięki opcji lib config możesz wybrać mapę do swojego projektu. Po prostu dodaj es2015.collectiondo swojej sekcji lib. Jeśli nie masz konfiguracji lib, dodaj jedną z ustawieniami domyślnymi i dodaj es2015.collection.

Więc kiedy masz target: es5, zmień tsconfig.json na:

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


0

Dodaj "target": "ESNEXT"właściwość do tsconfig.jsonpliku.

{
    "compilerOptions": {
        "target": "ESNEXT" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.