Mappa ES6 in dattiloscritto


173

Sto creando una classe in dattiloscritto che ha una proprietà che è una mappa ES6 (ECMAscript 2016) in questo modo:

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

Come posso dichiarare un tipo di mappa ES6 in dattiloscritto?

Risposte:


233

EDIT (5 giugno 2019): mentre l'idea che "TypeScript supporta in Mapmodo nativo" è ancora vera, poiché la versione 2.1 TypeScript supporta qualcosa chiamato Record.

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

Sfortunatamente il primo parametro generico (tipo chiave) non è ancora del tutto rispettato: anche con un stringtipo, qualcosa come peopleA[0](a number) è ancora valido.


MODIFICA (25 aprile 2016): la risposta che segue è vecchia e non deve essere considerata la risposta migliore. TypeScript ora supporta Maps "nativamente", quindi consente semplicemente di utilizzare ES6 Maps quando l'output è ES6. Per ES5, non fornisce polyfill; devi incorporarli tu stesso.

Per ulteriori informazioni, consultare la risposta di Mohamed Hegazy di seguito per una risposta più moderna, o anche questo commento reddit per una versione breve.


A partire dalla versione 1.5.0 beta, TypeScript non supporta ancora Maps . Non fa ancora parte della tabella di marcia .

La migliore soluzione attuale è un oggetto con chiave e valore digitati (a volte chiamato hashmap). Per un oggetto con chiavi di tipo stringe valori di tipo number:

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

Alcuni avvertimenti, tuttavia:

  1. le chiavi possono essere solo di tipo stringonumber
  2. In realtà non importa quale tipo di chiave utilizzi, poiché i numeri / le stringhe vengono comunque accettati in modo intercambiabile (viene applicato solo il valore).

Con l'esempio sopra:

// 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
Come si fa a ripetere le proprietà nella mappa? Quando eseguo arr.values ​​(), ottengo "Il valore 'Proprietà' non esiste sul tipo ..."
Vern Jensen,

Non lo stesso values(), farei for (var key in arr) ... arr[key]o for...of. Un'altra soluzione (che è sempre più realistica al giorno d'oggi e lo sarà per un po 'di tempo) è usare corejs .
zeh,

In effetti quando uso una chiave qualsiasi come proprietà su una mappa dichiarata in questo modo ottengo "Proprietà" qualunque "non esiste sul tipo"
rakslice

Sto usando la classe map per crearne una, ma anche se lo faccio map Map<string,string>=new Map<string,string>()quando map.set(something) ricevo un'eccezione map is undefined, c'è un altro modo per inizializzarla?
Mautrok,

1
Quando si prende di mira ES5, anche con i polyfill, non è possibile utilizzare alcune funzionalità - vedere github.com/Microsoft/TypeScript/issues/6842
Ondra Žižka

128

Vedi commento in: https://github.com/Microsoft/TypeScript/issues/3069#issuecomment-99964139

TypeScript non viene fornito con i pollyfill incorporati. sta a te decidere quale pollyfill usare, se presente. si può usare qualcosa come es6Collection , ES6-spessori , corejs .etc. Tutto ciò di cui ha bisogno il compilatore Typescript è una dichiarazione per i costrutti ES6 che si desidera utilizzare. puoi trovarli tutti in questo file lib .

ecco la parte pertinente:

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
Quando si prende di mira ES5, anche con i polyfill, non è possibile utilizzare alcune funzionalità - consultare github.com/Microsoft/TypeScript/issues/6842
Ondra Žižka


30

Sì Mappa ora è disponibile in dattiloscritto .. se guardi in lib.es6.d.ts, vedrai l'interfaccia:

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

È fantastico da usare come un dizionario di stringhe, coppie di oggetti .. l'unico fastidio è che se lo si utilizza per assegnare valori altrove con Map.get (chiave) l'IDE come il codice ti dà problemi sull'essere possibile non definito ... piuttosto che creazione di una variabile con un controllo definito .. è sufficiente eseguire il cast del tipo (supponendo che tu sappia per certo che la mappa ha la coppia chiave-valore)

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



4

Non sono sicuro che sia ufficiale, ma ha funzionato per me nel dattiloscritto 2.7.1:

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

In semplice Map<keyType, valueType>


3

Con l' opzione lib config sei in grado di selezionare la mappa nel tuo progetto. Aggiungi es2015.collectionalla sezione lib. Quando non hai lib config aggiungine uno con le impostazioni predefinite e aggiungi es2015.collection.

Quindi quando hai target: es5, cambia tsconfig.json in:

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


0

Aggiungi "target": "ESNEXT"proprietà al tsconfig.jsonfile.

{
    "compilerOptions": {
        "target": "ESNEXT" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.