Mapa ES6 en mecanografiado


174

Estoy creando una clase en mecanografiado que tiene una propiedad que es un mapa ES6 (ECMAscript 2016) así:

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

¿Cómo declaro un tipo de mapa ES6 en mecanografiado?

Respuestas:


234

EDITAR (5 de junio de 2019): Si bien la idea de que "TypeScript admite de Mapforma nativa" sigue siendo cierta, ya que la versión 2.1 TypeScript admite algo llamado Record.

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

Desafortunadamente, el primer parámetro genérico (tipo de clave) todavía no se respeta completamente: incluso con un stringtipo, algo como peopleA[0](a number) sigue siendo válido.


EDITAR (25 de abril de 2016): la respuesta a continuación es antigua y no debe considerarse la mejor respuesta. TypeScript ahora es compatible con Maps "nativamente", por lo que simplemente permite que se utilicen Maps ES6 cuando la salida es ES6. Para ES5, no proporciona polyfills; debes incrustarlos tú mismo.

Para obtener más información, consulte la respuesta de mohamed hegazy a continuación para obtener una respuesta más moderna, o incluso este comentario de reddit para una versión corta.


A partir de la versión 1.5.0 beta, TypeScript aún no es compatible con Maps . Tampoco es parte de la hoja de ruta .

La mejor solución actual es un objeto con clave y valor escritos (a veces llamado hashmap). Para un objeto con claves de tipo stringy valores de tipo number:

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

Algunas advertencias, sin embargo:

  1. las teclas solo pueden ser de tipo stringonumber
  2. En realidad, no importa lo que use como tipo de clave, ya que los números / cadenas todavía se aceptan indistintamente (solo se aplica el valor).

Con el ejemplo anterior:

// 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
¿Cómo, entonces, iterar las propiedades en el mapa? Cuando hago arr.values ​​(), obtengo "Property 'values' no existe en el tipo ..."
Vern Jensen

No es lo mismo que values()yo haría for (var key in arr) ... arr[key]o for...of. Otra solución (que es más y más realista hoy en día y lo será por un tiempo para muchas cosas) es usar corejs .
zeh

De hecho, cuando uso cualquier clave como propiedad en un mapa declarado de esta manera, obtengo "Propiedad 'lo que sea' que no existe en el tipo"
rakslice

Estoy usando la clase de mapa para construir uno, pero incluso si lo hago map Map<string,string>=new Map<string,string>()cuando map.set(something) obtengo una excepción map is undefined, ¿hay otra forma de inicializarla?
mautrok

1
Al apuntar a ES5, incluso con polyfills, no puede usar ciertas funciones: consulte github.com/Microsoft/TypeScript/issues/6842
Ondra Žižka

128

Ver comentario en: https://github.com/Microsoft/TypeScript/issues/3069#issuecomment-99964139

TypeScript no viene con pollyfills incorporados. depende de usted decidir qué pollyfill usar, si lo hay. puede usar algo como es6Collection , es6- shims , corejs ..etc. Todo lo que necesita el compilador de mecanografiado es una declaración para las construcciones ES6 que desea usar. Puedes encontrarlos en este archivo lib .

Aquí está la porción relevante:

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
Al apuntar a ES5, incluso con polyfills, no puede usar ciertas funciones: consulte github.com/Microsoft/TypeScript/issues/6842
Ondra Žižka


30

Sí Map ahora está disponible en mecanografiado ... si mira en lib.es6.d.ts, verá la interfaz:

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 ideal para usar como diccionario de cadenas, pares de objetos ... la única molestia es que si lo está utilizando para asignar valores en otro lugar con Map.get (clave), el IDE como Código le da problemas sobre la posibilidad de ser indefinido ... en lugar de crear una variable con una verificación está definida ... simplemente eche el tipo (suponiendo que sepa con certeza que el mapa tiene el par clave-valor)

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



4

No estoy seguro de si esto es oficial pero funcionó para mí en el mecanografiado 2.7.1:

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

En simple Map<keyType, valueType>




0

Agregar "target": "ESNEXT"propiedad al tsconfig.jsonarchivo.

{
    "compilerOptions": {
        "target": "ESNEXT" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
    }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.