Verwenden der Spread-Syntax und des neuen Set () mit Typoskript


90

Ich verwende folgenden Code, um eindeutige Nummern zu erhalten:

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

Typoskript meldet jedoch folgenden Fehler: Typ 'Set' ist kein Array-Typ. Ich bin kein Typoskript-Ninja. Kann mir jemand sagen, was hier falsch ist?


4
Ich denke, das ist nur ein Typescript-Fehler, wenn die Version, die Sie verwenden, behauptet, ES2015 zu unterstützen.
Pointy

1
@Pointy Entschuldigung, ich sollte eine Version von tsc einschließen, die 1.6.2
Eggy

Antworten:


39

Dies ist eine fehlende Funktion. TypeScript unterstützt derzeit nur iterables auf Arrays.


Danke für die Klarstellung. Ich werde .filter () oder etwas anderes verwenden, um die Arbeit zu erledigen. Ich habe auch einige Probleme mit diesem speziellen Fehler auf github gefunden. Ich werde dies in zukünftigen Versionen im Auge behalten.
Eggy

94

Update : Mit Typescript 2.3 können Sie jetzt "downlevelIteration": truezu Ihrer tsconfig hinzufügen. Dies funktioniert beim Targeting von ES5.

Der Nachteil downlevelIterationist, dass TS beim Transpilieren ziemlich viel Boilerplate einspritzen muss. Die einzelne Zeile aus der Frage wird mit 21 Zeilen hinzugefügter Boilerplate transpiliert: (ab Typescript 2.6.1)

Diese Boilerplate wird einmal pro Datei injiziert, die eine Downlevel-Iteration verwendet, und diese Boilerplate kann mithilfe der "importHelpers"Option über die tsconfig reduziert werden . (Siehe diesen Blogpost zur Downlevel-Iteration und importHelpers)

Wenn die ES5-Unterstützung für Sie keine Rolle spielt, können Sie alternativ immer zuerst "es6" als Ziel festlegen. In diesem Fall funktioniert der ursprüngliche Code, ohne das Flag "downlevelIteration" zu benötigen.


Ursprüngliche Antwort:

Dies scheint eine maschinengeschriebene ES6-Transpilations-Eigenart zu sein. Der ...Operator sollte an allem arbeiten, was eine Iterator-Eigenschaft hat (Zugriff durch obj[Symbol.iterator]), und Sets haben diese Eigenschaft.

Um dies zu umgehen, können Sie Array.fromden Satz zuerst in ein Array konvertieren : ...Array.from(new Set([1, 2, 3, 1, 1])).


@Restam: Stellt Typoskript Polyfills für Array.from im IE bereit, wenn "target": "es5" in tsconfig.json?
JackOfAll

1
@jackOfAll Nein, Typescript füllt keine Prototypen für Sie aus. Wenn Sie "target": "es5" festlegen, sollte ein Compilerfehler angezeigt werden, wenn Sie versuchen, eine Methode zu verwenden, die mehrfach ausgefüllt werden muss.
Retsam

1
@Restam tolle Lösung mit Array.from. Die meisten anderen Leute scheinen dies einfach aufzugeben. Danke für eine echte Lösung!
Rayepps

Es ist kein Fehler, sie unterstützen ihn nur nicht für das es5Ziel (siehe github.com/Microsoft/TypeScript/issues/4031 ). Array.fromsollte funktionieren, wenn Sie es2015oder höher ( es2017, esnext) in Ihrer libListe in tsconfig haben.
Simon Hänisch

1
@ SimonHänisch Danke für den Link: Ich habe meine Antwort aktualisiert, ich nenne sie nicht mehr "Bug", sondern "Transpilation Quirk", was wahrscheinlich ein genauerer Begriff ist. Über diesen Link habe ich auch Informationen zur Downlevel-Iterationsoption hinzugefügt, wodurch auch das ursprüngliche Problem behoben wird.
Retsam

64

Sie können auch die Array.from-Methode verwenden, um das Set in Array zu konvertieren

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


Was bringt es, das Array nur zu verbreiten, um es in einem neuen Array wieder zu erfassen?
Robby Cornelissen

1
Wenn es nicht möglich ist, "es6" in tsconfig anzuvisieren. Und wie wäre es, Set mit Spread-Operator zu verwenden?
Nate Getch

Der Punkt ist, dass Sie bei Verwendung Array.from()den Spread-Operator nicht mehr benötigen. Es fügt nur Overhead hinzu. let uniques = Array.from(new Set([1, 2, 3, 1, 1]));
Robby Cornelissen

8

Sie müssen "target": "es6",in Ihrer tsconfig einstellen.


0

Damit es funktioniert, benötigen Sie entweder "target": "ES6" (oder höher) oder "downlevelIteration": true in den compilerOptions Ihrer tsconfig.json. Dies hat mein Problem gelöst und funktioniert gut oder ich. Ich hoffe, es wird Ihnen auch helfen.


-1

In Javascript:

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

Im Typoskript:

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

Im Reaktionszustand (setState):

setCart(Array.from(new Set([...cart, {title: 'Sample', price: 20}])));
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.