بنية الانتشار - TypeScript 2.8.3 يجب أن يكون للنمط طريقة Symbol.iterator تعيد مكرراً
أنا أواجه خطأ يقول
Type must have a '[Symbol.iterator]()' method that returns an iterator.
يأمل على الخط المحدد:
class Test {
private async do() {
const done = [...(await this.test())]; // Here's the error
}
private async *test(): AsyncIterableIterator<string> {
return;
}
}
لقد وجدت بعض المشاكل في مستودع TypeScript على GitHub، لكن لا يبدو أن أيًا منها قد ساعد. كلها تقترح إضافة إدخالات جديدة إلى lib. أنا أستخدم هدف es6 وقد أضفت esnext وdom وes2018. هذا لم يؤثر على الخطأ إطلاقًا.
هل أفتقد المزيد من إدخالات lib (وهو ما أشك فيه لأن تلك التي أستخدمها هي الإدخالات الشاملة التي تحتوي على كل شيء) أم أن الكود الذي أستخدمه غير صالح؟
الإجابة رقم 1
هذا ساعدني. في tsconfig، أضف هذا:
{
"compilerOptions": {
"lib": [
"es5", "es6", "dom", "dom.iterable"
]
}
}
هذا مطلوب لـ tsconfig لمعرفة أي الواجهات يجب استيرادها أثناء ترجمة شفرتك.
dom.iterable يشمل جميع الواجهات المذكورة هنا: https://github.com/microsoft/TypeScript/blob/main/src/lib/dom.iterable.d.ts
كما أشكر @domlas على ذكر هذا. لقد قمت بالفعل بالتصويت لصالح تعليقه حتى يُعتبر السبب الافتراضي.
الإجابة رقم 2
أعتقد أنه يمكنك التخلص من الخطأ إذا قمت بـتحويل "this.test()" إلى سلسلة أو مصوفة.
كانت حالتي مختلفة، لكن أعتقد أن حلولتي قد تساعد بعض المطورين الزملاء.
رسالة الخطأ التي ظهرت لي كانت:
Type 'Ingredient | Ingredient[]' must have a '[Symbol.iterator]()'
method that returns an iterator
حاولت عدة طرق، وكانت الطرق الثلاث التالية الثلاث ناجحة، مع كون الطريقة الأولى الأبسط:
الإجابة رقم 3
يحدث الخطأ "Type Object must have a Symbol.iterator method that returns an iterator" عندما نحاول استخدام بنية الانتشار (...) لفك كائن داخل مصفوفة. لحل الخطأ، قم بتغليف كائنك في مصفوفة أو صحح أنواعك المعلنة.
مثل هذا..
const obj = { name: 'James' };
// ⛔️ Error: Type Object must have a '[Symbol.iterator]()'
// method that returns an iterator.ts(2488)
const result = [...obj];
حاولنا استخدام صياغة الانتشار لتفكيك خصائص كائن مباشرة إلى مصفوفة.
الحل لهذا يعتمد على حالة الاستخدام الخاصة بك. إذا كنت تريد تفكيك الكائن إلى مصفوفة، قم بتغليفه في مصفوفة قبل استخدام صيغة الانتشار (...).
const obj = { name: 'James' };
const result = [...[obj]];
console.log(result); // 👉️ [{name: 'James'}]
المصدر هنا
الإجابة رقم 4
كما علقت أعلاه، فإن عامل الانتشار للأسف غير مدعوم حالياً للمكررات غير المتزامنة. القضية ذات الصلة على GitHub هي tc39/proposal-async-iteration#103.
ملخص من تلك المسألة (باستثناء الأشياء الزائدة مثل "يمكنك فعل ذلك بهذه الطريقة، أوه لا لا يمكنك، لا بأس"):
@jedwards1211 قال:
هل سيكون دعم عامل نشر المصفوفة جزءًا من هذا الاقتراح في أي وقت؟
@دومينيك أجاب:
ليس جزءا من هذا الاقتراح... اقتراح آخر قد يتصور بالتأكيد شيئا جديدا هنا.
ولا أرى اقتراحًا في مكان آخر (هل تريد بدء واحد؟). على أي حال، بما أنه ليس جزءًا حتى من JavaScript ESNext، فمن المحتمل ألا يتم إضافته إلى TypeScript.
البديل الأكثر قابلية للتطبيق هو بناء الجملة for await المفصل في إجابة @estus. آسف لأنني لم أستطع أن أكون أكثر فائدة. حظاً سعيداً!
الإجابة رقم 5
على الرغم مما قد يوحي به الصياغة النحوية، فإن دالة المولد غير المتزامن ليست دالة async تُرجع مولدًا.
كما ينص الاقتراح،
دوال المولد غير المتزامنة مشابهة لدوال المولد، مع الفروقات التالية:
عند الاستدعاء، تُعيد دوال المولدات غير المتزامنة كائنًا، وهو مولد غير متزامن تُعيد طرقه (next و throw و return) وعودًا لقيم { value, done }، بدلاً من إعادة { value, done } مباشرة. هذا يجعل كائنات المولدات غير المتزامنة المعادة تلقائيًا قابلة للتكرار غير المتزامن.
إنه يُعيد مولدًا غير متزامن، وليس وعدًا، لذا فإن استخدام await عليه لا يجدي نفعًا.
نظرًا لأن المولد غير المتزامن يحتوي على Symbol.asyncIterator بدلاً من Symbol.iterator، فهو عبارة عن مكرر غير قابل للتكرار، أي أنه لا يمكن تكراره باستخدام طرق ES6 العادية (Array.from، for..of، تركيب الانتشار، إلخ). هذا هو السبب في تقديم for await..of.
يجب أن يكون الكود أعلاه:
const values = [];
for await (const value of this.test()) {
values.push(v);
}
يمكن تحويل التكرار على المكرر غير المتزامن بنفس طريقة المكررات العادية، الاختلاف هو أن next() ترجع وعدًا بالقيمة التالية، وليس القيمة نفسها:
const iterator = this.test();
let next;
while ((next = await iterator.next()).done === false) {
values.push(next.value);
}
نظرًا لأن مواصفة المولد غير المتزامن هي اقتراح، فإن الدعم للمكررات غير المتزامنة في طرق التكرار في ES6 قد يكون عرضة للتغيير.



