Carte ES6 dans Typescript


174

Je crée une classe en tapuscript qui a une propriété qui est une carte ES6 (ECMAscript 2016) comme ceci:

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

Comment déclarer un type de carte ES6 dans un script dactylographié?

Réponses:


234

EDIT (5 juin 2019): Alors que l'idée que "TypeScript prend Mapen charge nativement" est toujours vraie, puisque la version 2.1 TypeScript prend en charge quelque chose appelé Record.

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

Malheureusement, le premier paramètre générique (type de clé) n'est toujours pas pleinement respecté: même avec un stringtype, quelque chose comme peopleA[0](a number) est toujours valide.


EDIT (25 avril 2016): La réponse ci-dessous est ancienne et ne doit pas être considérée comme la meilleure réponse. TypeScript prend désormais en charge les cartes "nativement", donc il permet simplement d'utiliser les cartes ES6 lorsque la sortie est ES6. Pour ES5, il ne fournit pas de polyfills; vous devez les intégrer vous-même.

Pour plus d'informations, reportez-vous à la réponse de mohamed hegazy ci-dessous pour une réponse plus moderne, ou même à ce commentaire reddit pour une version courte.


Depuis la version 1.5.0 beta, TypeScript ne prend pas encore en charge les cartes . Cela ne fait pas encore partie de la feuille de route non plus.

La meilleure solution actuelle est un objet avec une clé et une valeur tapées (parfois appelé hashmap). Pour un objet avec des clés de type stringet des valeurs de type number:

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

Quelques mises en garde, cependant:

  1. les clés ne peuvent être que de type stringounumber
  2. Peu importe ce que vous utilisez comme type de clé, car les nombres / chaînes sont toujours acceptés de manière interchangeable (seule la valeur est appliquée).

Avec l'exemple ci-dessus:

// 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
Comment alors parcourez-vous les propriétés de la carte? Quand je fais arr.values ​​(), j'obtiens "La propriété 'valeurs' n'existe pas sur le type ..."
Vern Jensen

Pas la même chose que values(), je ferais for (var key in arr) ... arr[key]ou for...of. Une autre solution (qui est de plus en plus réaliste de nos jours et le sera pendant un certain temps pour beaucoup de choses) est d'utiliser corejs .
zeh

En fait, lorsque j'utilise une clé comme propriété sur une carte déclarée de cette manière, j'obtiens "La propriété 'n'importe quoi' n'existe pas sur le type"
rakslice

J'utilise la classe map pour en créer une, mais même si je le fais map Map<string,string>=new Map<string,string>()lorsque map.set(something) j'obtiens une exception map is undefined, existe-t-il un autre moyen de l'initialiser?
mautrok

1
Lorsque vous ciblez ES5, même avec des polyfills, vous ne pouvez pas utiliser certaines fonctionnalités - voir github.com/Microsoft/TypeScript/issues/6842
Ondra Žižka

128

Voir le commentaire dans: https://github.com/Microsoft/TypeScript/issues/3069#issuecomment-99964139

TypeScript n'est pas fourni avec des pollyfills intégrés. c'est à vous de décider quel pollyfill utiliser, le cas échéant. vous pouvez utiliser quelque chose comme es6Collection , es6-shims , corejs ..etc. Tout ce dont le compilateur Typescript a besoin est une déclaration pour les constructions ES6 que vous souhaitez utiliser. vous pouvez tous les trouver dans ce fichier lib .

voici la partie 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
Lorsque vous ciblez ES5, même avec des polyfills, vous ne pouvez pas utiliser certaines fonctionnalités - voir github.com/Microsoft/TypeScript/issues/6842
Ondra Žižka


30

Oui Map est maintenant disponible en typographie .. si vous regardez dans lib.es6.d.ts, vous verrez l'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;} 

C'est génial à utiliser comme dictionnaire de chaînes, de paires d'objets .. le seul inconvénient est que si vous l'utilisez pour attribuer des valeurs ailleurs avec Map.get (clé), l'EDI comme Code vous pose des problèmes sur le fait d'être éventuellement indéfini .. plutôt que création d'une variable avec une vérification est définie .. il suffit de lancer le type (en supposant que vous soyez sûr que la carte a la paire clé-valeur)

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



4

Je ne sais pas si c'est officiel, mais cela a fonctionné pour moi dans le typographie 2.7.1:

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

En simple Map<keyType, valueType>


3

Avec l' option lib config, vous pouvez choisir Map dans votre projet. Ajoutez simplement es2015.collectionà votre section lib. Lorsque vous n'avez pas de configuration de lib, ajoutez-en une avec les valeurs par défaut et ajoutez es2015.collection.

Ainsi, lorsque vous avez target: es5, remplacez tsconfig.json par:

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


0

Ajoutez une "target": "ESNEXT"propriété au tsconfig.jsonfichier.

{
    "compilerOptions": {
        "target": "ESNEXT" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
    }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.