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?

Eggy
quelle
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.

Basarat
quelle
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])).

Retsam
quelle
@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);

Nate Getch
quelle
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.

phil294
quelle
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.

Mayur Saner
quelle
-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}])));
Najathi
quelle