ES6-Karte in Typoskript

173

Ich erstelle eine Klasse in Typoskript mit einer Eigenschaft, die eine ES6-Map (ECMAscript 2016) ist, wie folgt:

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

Wie deklariere ich einen ES6-Map-Typ in Typoskript?

Nicksrandall
quelle

Antworten:

233

BEARBEITEN (5. Juni 2019): Während die Idee, dass "TypeScript Mapnativ unterstützt ", immer noch wahr ist, unterstützt TypeScript in Version 2.1 etwas, das so genannt wird Record.

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

Leider wird der erste generische Parameter (Schlüsseltyp) immer noch nicht vollständig berücksichtigt: Selbst bei einem stringTyp ist so etwas wie peopleA[0](a number) immer noch gültig.


BEARBEITEN (25. April 2016): Die Antwort unten ist alt und sollte nicht als die beste Antwort angesehen werden. TypeScript unterstützt Maps jetzt "nativ", sodass ES6-Maps einfach verwendet werden können, wenn die Ausgabe ES6 ist. Für ES5 werden keine Polyfills bereitgestellt. Sie müssen sie selbst einbetten.

Weitere Informationen finden Sie in der Antwort von mohamed hegazy unten, um eine modernere Antwort zu erhalten, oder sogar in diesem reddit-Kommentar für eine Kurzversion.


Ab der Beta-Version 1.5.0 unterstützt TypeScript Maps noch nicht . Es ist auch noch nicht Teil der Roadmap .

Die derzeit beste Lösung ist ein Objekt mit eingegebenem Schlüssel und Wert (manchmal auch als Hashmap bezeichnet). Für ein Objekt mit Schlüsseln vom Typ stringund Werten vom Typ number:

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

Einige Einschränkungen jedoch:

  1. Schlüssel können nur vom Typ stringoder seinnumber
  2. Es spielt eigentlich keine Rolle, was Sie als Schlüsseltyp verwenden, da Zahlen / Zeichenfolgen immer noch austauschbar akzeptiert werden (nur der Wert wird erzwungen).

Mit dem obigen Beispiel:

// 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
zeh
quelle
3
Wie iterieren Sie dann die Eigenschaften in der Karte? Wenn ich arr.values ​​() mache, erhalte ich "Property 'values' existiert nicht für Typ ..."
Vern Jensen
Nicht das gleiche wie values()ich würde for (var key in arr) ... arr[key]oder for...of. Eine andere Lösung (die heutzutage immer realistischer ist und für eine Weile für viele Dinge gelten wird) ist die Verwendung von corejs .
zeh
In der Tat, wenn ich einen Schlüssel als Eigenschaft auf einer Karte verwende, die auf diese Weise deklariert wurde, erhalte ich "Eigenschaft 'was auch immer' existiert nicht auf Typ"
Rakslice
Ich verwende die Karte Klasse zu bauen ein, aber selbst wenn ich tun , map Map<string,string>=new Map<string,string>()wenn ich tue map.set(something) ich eine Ausnahme erhalten map is undefined, gibt es eine andere Möglichkeit , es zu initialisieren?
mautrok
1
Wenn Sie auf ES5 abzielen, können Sie selbst mit Polyfills bestimmte Funktionen nicht verwenden - siehe github.com/Microsoft/TypeScript/issues/6842
Ondra Žižka
128

Siehe Kommentar in: https://github.com/Microsoft/TypeScript/issues/3069#issuecomment-99964139

TypeScript wird nicht mit integrierten Pollyfills geliefert. Es liegt an Ihnen, zu entscheiden, welche Pollyfill gegebenenfalls verwendet werden soll. Sie können so etwas wie es6Collection , es6- shims , corejs ..etc verwenden. Der Typescript-Compiler benötigt lediglich eine Deklaration für die ES6-Konstrukte, die Sie verwenden möchten. Sie finden sie alle in dieser lib-Datei .

Hier ist der relevante Teil:

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;
mohamed hegazy
quelle
3
Wenn Sie auf ES5 abzielen, können Sie selbst mit Polyfills bestimmte Funktionen nicht verwenden - siehe github.com/Microsoft/TypeScript/issues/6842
Ondra Žižka
30

Ja, Map ist jetzt in Typoskript verfügbar. Wenn Sie in lib.es6.d.ts nachsehen, sehen Sie die Oberfläche:

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

Es ist großartig, es als Wörterbuch für Zeichenfolgen und Objektpaare zu verwenden. Das einzige Ärgernis ist, dass der IDE-ähnliche Code Ihnen Probleme gibt , wenn Sie es verwenden, um Werte an anderer Stelle mit Map.get (Schlüssel) zuzuweisen Erstellen einer Variablen mit einer definierten Prüfung. Geben Sie einfach den Typ um (vorausgesetzt, Sie wissen, dass die Karte das Schlüssel-Wert-Paar enthält).

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

Ich bin mir nicht sicher, ob dies offiziell ist, aber dies hat bei mir in Typoskript 2.7.1 funktioniert:

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

In einfachen Worten Map<keyType, valueType>

Jonas Tomanga
quelle
3

Mit der Option lib config können Sie Map in Ihr Projekt aufnehmen. Fügen es2015.collectionSie einfach Ihren lib-Bereich hinzu. Wenn Sie keine lib-Konfiguration haben, fügen Sie eine mit den Standardeinstellungen hinzu und fügen Sie hinzu es2015.collection.

Wenn Sie also das Ziel: es5 haben, ändern Sie tsconfig.json in:

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

Fügen Sie "target": "ESNEXT"der tsconfig.jsonDatei eine Eigenschaft hinzu .

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