Utilisation de la syntaxe de diffusion et du nouveau Set () avec dactylographié

92

J'utilise le code suivant pour obtenir des numéros uniques:

let uniques = [ ...new Set([1, 2, 3, 1, 1]) ]; // [1, 2, 3]

Toutefois, dactylographié signale l'erreur suivante: Le type «Set» n'est pas un type de tableau. Je ne suis pas un ninja dactylographié, quelqu'un pourrait-il me dire ce qui ne va pas ici?

Eggy
la source
4
Je pense que ce n'est qu'un bogue de Typescript, si la version que vous utilisez prétend prendre en charge ES2015.
Pointy
1
@Pointy Désolé à ce sujet, je devrais inclure la version de tsc qui est 1.6.2
Eggy

Réponses:

39

C'est une fonctionnalité manquante. TypeScript ne prend en charge que les itérables sur les tableaux pour le moment.

basarat
la source
Merci pour la clarification. J'utiliserai .filter () ou autre chose pour faire le travail. J'ai également trouvé quelques problèmes sur github à propos de cette erreur particulière. Je garderai un œil sur cela dans les prochaines versions.
Eggy
96

Mise à jour : Avec Typescript 2.3, vous pouvez maintenant ajouter "downlevelIteration": trueà votre tsconfig, et cela fonctionnera tout en ciblant ES5.

L'inconvénient downlevelIterationest que TS devra injecter un peu de passe-partout lors du transpilage. La seule ligne de la question transpile avec 21 lignes de passe-partout ajouté: (à partir de Typescript 2.6.1)

Ce passe-partout sera injecté une fois par fichier qui utilise une itération de bas niveau, et ce passe-partout peut être réduit en utilisant l' "importHelpers"option via le tsconfig. (Voir cet article de blog sur l'itération de bas niveau et importHelpers)

Sinon, si la prise en charge d'ES5 n'a pas d'importance pour vous, vous pouvez toujours cibler simplement "es6" en premier lieu, auquel cas le code d'origine fonctionne sans avoir besoin de l'indicateur "downlevelIteration".


Réponse originale:

Cela semble être une bizarrerie de transpilation dactylographiée ES6. L' ...opérateur doit travailler sur tout ce qui a une propriété d'itérateur, (Accès par obj[Symbol.iterator]) et les ensembles ont cette propriété.

Pour contourner ce problème, vous pouvez utiliser Array.frompour convertir d' abord le jeu à un tableau: ...Array.from(new Set([1, 2, 3, 1, 1])).

Retsam
la source
@Restam: Est-ce que typescript fournit des polyfills pour Array.from dans IE si "target": "es5" dans tsconfig.json?
jackOfAll
1
@jackOfAll Non, Typescript ne fait pas de polyfilling des prototypes pour vous. Si vous définissez "target": "es5", cela devrait vous donner une erreur de compilation si vous essayez d'utiliser une méthode qui doit être polyfilled.
Retsam
1
@Restam excellente solution avec Array.from. La plupart des autres semblent simplement abandonner cela. merci pour une vraie solution!
rayepps
Ce n'est pas un bogue, ils ne le prennent tout simplement pas en charge pour la es5cible (voir github.com/Microsoft/TypeScript/issues/4031 ). Array.fromdevrait fonctionner si vous avez es2015ou plus ( es2017, esnext) dans votre libliste dans tsconfig.
Simon Hänisch
1
@ SimonHänisch Merci pour le lien: j'ai mis à jour ma réponse, je ne l'appelle plus un "bug", mais une "bizarrerie de transpilation", qui est probablement un terme plus précis. J'ai également ajouté des informations sur l'option d'itération de niveau inférieur à partir de ce lien, qui résout également le problème d'origine.
Retsam
67

Vous pouvez également utiliser la méthode Array.from pour convertir l'ensemble en tableau

let uniques = Array.from(new Set([1, 2, 3, 1, 1])) ;
console.log(uniques);

Nate Getch
la source
Quel est l'intérêt de diffuser le tableau uniquement pour le recapturer dans un nouveau tableau?
Robby Cornelissen
1
S'il n'est pas possible de cibler "es6", dans tsconfig. Et l'utilisation de Set avec l'opérateur de propagation est requise, comment feriez-vous?
Nate Getch le
Le fait est que si vous utilisez Array.from(), vous n'avez plus besoin de l'opérateur de propagation. Cela ne fait qu'ajouter des frais généraux. let uniques = Array.from(new Set([1, 2, 3, 1, 1]));
Robby Cornelissen
8

Vous devez définir "target": "es6",dans votre tsconfig.

phil294
la source
0

Pour le faire fonctionner, vous avez besoin de "target": "ES6" (ou supérieur) ou "downlevelIteration": true dans les options de compilation de votre tsconfig.json. Cela a résolu mon problème et fonctionne bien ou moi. J'espère que cela vous aidera également.

Mayur Saner
la source
-1

En Javascript:

[ ...new Set([1, 2, 3, 1, 1]) ]

En texte manuscrit:

Array.from(new Set([1, 2, 3, 1, 1]))

Dans l'état de réaction (setState):

setCart(Array.from(new Set([...cart, {title: 'Sample', price: 20}])));
Najathi
la source