Website-Suche

Spread-Syntax - TypeScript 2.8.3 Typ muss eine Symbol.iterator-Methode haben, die einen Iterator zurückgibt


Ich stoße auf einen Fehler, der sagt

Type must have a '[Symbol.iterator]()' method that returns an iterator.

Es hofft auf der abgesteckten Linie:

class Test {
    private async do() {
        const done = [...(await this.test())]; // Here's the error
    }

    private async *test(): AsyncIterableIterator<string> {
        return;
    }
}

Ich habe einige Probleme im TypeScript GitHub-Repository gefunden, aber keines scheint geholfen zu haben. Sie alle schlagen vor, neue Einträge zu lib hinzuzufügen. Ich verwende das es6-Ziel und habe esnext, dom und es2018 hinzugefügt. Dies hatte keinerlei Einfluss auf den Fehler.

Fehlen mir mehr lib-Einträge (was ich bezweifle, da die, die ich benutze, die Allround-Einträge mit allem darin sind) oder ist der Code, den ich benutze, ungültig?

Antwort #1

Das hat mir geholfen. Füge dies in tsconfig ein:

{
    "compilerOptions": {
        "lib": [
            "es5", "es6", "dom", "dom.iterable"
        ]
    }
}

Dies ist erforderlich, damit tsconfig weiß, welche Schnittstellen beim Transpilieren Ihres Codes importiert werden sollen.

dom.iterable enthält alle hier erwähnten Schnittstellen: https://github.com/microsoft/TypeScript/blob/main/src/lib/dom.iterable.d.ts

Also danke an @domlas, dass er das erwähnt hat. Ich habe seinen Kommentar bereits hochgevotet, damit er als Standardgrund behandelt wird.

Antwort #2

Ich denke, du kannst den Fehler loswerden, wenn du "this.test()" zu string oder array castest.

Meine Situation war anders, aber ich denke, meine Lösungen könnten einigen anderen Entwicklern helfen.

Die Fehlermeldung, die ich erhalten habe, war:

     Type 'Ingredient | Ingredient[]' must have a '[Symbol.iterator]()' 
     method that returns an iterator

Ich habe ein paar Möglichkeiten ausprobiert, und die folgenden DREI haben funktioniert, wobei die ERSTE die einfachste war:

Antwort #3

Der Fehler "Type Object must have a Symbol.iterator method that returns an iterator" tritt auf, wenn wir versuchen, die Spread-Syntax (...) zu verwenden, um ein Objekt in einem Array zu entpacken. Um den Fehler zu beheben, wickeln Sie Ihr Objekt in ein Array oder korrigieren Sie Ihre Typdefinitionen.

so..

const obj = { name: 'James' };

// ⛔️ Error: Type Object must have a '[Symbol.iterator]()'
// method that returns an iterator.ts(2488)
const result = [...obj];

Wir haben versucht, die Spread-Syntax zu verwenden, um die Eigenschaften eines Objekts direkt in ein Array zu entpacken.

Die Lösung hierfür hängt von Ihrem Anwendungsfall ab. Wenn Sie das Objekt in ein Array entpacken möchten, fügen Sie es in ein Array ein, bevor Sie die Spread-Syntax (...) verwenden.

 const obj = { name: 'James' };

const result = [...[obj]];

console.log(result); // 👉️ [{name: 'James'}]

Quelle hier

Antwort #4

Wie ich oben kommentiert habe, wird der Spread-Operator leider derzeit für asynchrone Iteratoren nicht unterstützt. Das relevante Problem auf GitHub ist tc39/proposal-async-iteration#103.

Zusammenfassung dieses Problems (ohne überflüssige Dinge wie „du könntest es auf diese Weise machen, oh nein, geht doch nicht, egal“):

@jedwards1211 sagte:

Wird die Unterstützung des Array-Spread-Operators jemals Teil dieses Vorschlags sein?

@domenic antwortete:

Nicht Teil dieses Vorschlags... Ein anderer Vorschlag könnte hier sicherlich etwas Neues in Betracht ziehen.

Und ich sehe keinen Vorschlag anderswo (willst du einen starten?). Auf jeden Fall, da es nicht einmal Teil von JavaScript ESNext ist, wird es höchstwahrscheinlich nicht zu TypeScript hinzugefügt werden.

Die praktikabelste Alternative ist die for await-Syntax, die in Estus' Antwort erläutert wird. Es tut mir leid, dass ich nicht hilfreicher sein konnte. Viel Glück!

Antwort #5

Trotz dessen, was die Syntax vermuten lässt, ist eine asynchrone Generatorfunktion keine async-Funktion, die einen Generator zurückgibt.

Wie der Vorschlag darlegt,

Asynchrone Generatorfunktionen sind Generatorfunktionen ähnlich, mit den folgenden Unterschieden:

Wenn sie aufgerufen werden, geben asynchrone Generatorfunktionen ein Objekt zurück, einen asynchronen Generator, dessen Methoden (next, throw und return) Versprechen für { value, done } zurückgeben, anstatt direkt { value, done } zurückzugeben. Dies macht die zurückgegebenen asynchronen Generatorobjekte automatisch zu asynchronen Iteratoren.

Es gibt einen asynchronen Generator zurück, kein Promise, daher bringt es nichts, ihn mit await zu verwenden.

Da der asynchrone Generator Symbol.asyncIterator anstelle von Symbol.iterator hat, ist er ein nicht-iterierbarer Iterator, d.h. er kann nicht mit den regulären ES6-Methoden (Array.from, for..of, Spread-Syntax usw.) durchlaufen werden. Aus diesem Grund wurde for await..of eingeführt.

Der obige Code sollte sein:

const values = [];

for await (const value of this.test()) {
  values.push(v);
}

Die Iteration über einen asynchronen Iterator kann ähnlich wie bei regulären Iteratoren desugariert werden, der Unterschied besteht darin, dass next() ein Versprechen des nächsten Wertes zurückgibt, nicht den Wert selbst:

const iterator = this.test();
let next;
       
while ((next = await iterator.next()).done === false) {
  values.push(next.value);
}

Da die Spezifikation für asynchrone Generatoren ein Vorschlag ist, kann die Unterstützung für asynchrone Iteratoren in ES6-Iteratormethoden Änderungen unterliegen.

Verwandte Artikel