Mapa ES6 em texto datilografado

173

Estou criando uma classe no texto datilografado que possui uma propriedade que é um mapa do ES6 (ECMAscript 2016), assim:

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

Como declaro um tipo de mapa ES6 em texto datilografado?

nicksrandall
fonte

Respostas:

233

EDIT (5 de junho de 2019): Embora a ideia de que "o TypeScript suporta Mapnativamente" ainda seja verdadeira, desde a versão 2.1 o TypeScript suporta algo chamado Record.

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

Infelizmente, o primeiro parâmetro genérico (tipo de chave) ainda não é totalmente respeitado: mesmo com um stringtipo, algo como peopleA[0](a number) ainda é válido.


EDIT (25 de abril de 2016): A resposta abaixo é antiga e não deve ser considerada a melhor resposta. O TypeScript oferece suporte ao Maps "nativamente" agora, portanto, simplesmente permite que o ES6 Maps seja usado quando a saída for ES6. Para o ES5, ele não fornece polyfills; você precisa incorporá-los você mesmo.

Para obter mais informações, consulte a resposta de mohamed hegazy abaixo para obter uma resposta mais moderna, ou mesmo este comentário no reddit para uma versão curta.


A partir da versão 1.5.0 beta, o TypeScript ainda não suporta Mapas . Ainda não faz parte do roteiro .

A melhor solução atual é um objeto com chave e valor digitados (às vezes chamado de hashmap). Para um objeto com chaves do tipo stringe valores do tipo number:

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

Algumas advertências, no entanto:

  1. As chaves podem ser apenas do tipo stringounumber
  2. Na verdade, não importa o que você usa como o tipo de chave, pois os números / seqüências de caracteres ainda são aceitos de forma intercambiável (apenas o valor é imposto).

Com o exemplo acima:

// 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
fonte
3
Como, então, você itera as propriedades no mapa? Quando eu faço arr.values ​​(), recebo "Property 'values' não existe no tipo ..." #
7277 Vern Jensen
Não é o mesmo que values(), eu faria for (var key in arr) ... arr[key]ou for...of. Outra solução (que é cada vez mais realista hoje em dia e será um bom tempo para muitas coisas) é usar o corejs .
zeh 3/09/15
De fato, quando eu uso qualquer chave como uma propriedade em um mapa declarado dessa maneira, recebo "Propriedade 'o que quer que seja' não existe no tipo" "
rakslice 19/03/16
Estou usando a classe map para criar uma, mas, mesmo que map Map<string,string>=new Map<string,string>()eu o faça map.set(something) , recebo uma exceção map is undefined, existe outra maneira de inicializá-la?
Mautrok
1
Ao direcionar o ES5, mesmo com polyfills, você não pode usar determinados recursos - consulte github.com/Microsoft/TypeScript/issues/6842
Ondra de
128

Veja o comentário em: https://github.com/Microsoft/TypeScript/issues/3069#issuecomment-99964139

O TypeScript não vem com pollyfills integrados. cabe a você decidir qual pollyfill usar, se houver. você pode usar algo como es6Collection , ES6-calços , corejs .etc. Todas as necessidades do compilador Typescript são uma declaração para as construções do ES6 que você deseja usar. você pode encontrá-los todos neste arquivo lib .

aqui está a parte 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;
mohamed hegazy
fonte
3
Ao segmentar o ES5, mesmo com polyfills, você não pode usar determinados recursos - consulte github.com/Microsoft/TypeScript/issues/6842
Ondra de
30

Sim O mapa está agora disponível em texto datilografado. Se você procurar em lib.es6.d.ts, verá a interface:

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

É ótimo usar como dicionário de cadeia de caracteres, pares de objetos .. o único incômodo é que, se você estiver usando para atribuir valores em outro lugar com Map.get (key), o IDE como Código lhe dará problemas em ser possível indefinido .. em vez de criando uma variável com uma verificação definida. basta converter o tipo (supondo que você tenha certeza de que o mapa possui o par de valores-chave)

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

Não tenho certeza se isso é oficial, mas isso funcionou para mim no texto datilografado 2.7.1:

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

Em simples Map<keyType, valueType>

Jonas Tomanga
fonte
3

Com a opção lib config, você pode escolher o mapa no seu projeto. Basta adicionar es2015.collectionà sua seção lib. Quando você não possui uma configuração lib, adicione uma com os padrões e adicionees2015.collection .

Portanto, quando você tiver o target: es5, altere tsconfig.json para:

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

Adicione "target": "ESNEXT"propriedade ao tsconfig.jsonarquivo.

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