typescript - TS2318: Nu se poate găsi tipul global 'AsyncIterableIterator' - generator asincron
Am un generator asincron:
async function* foo() {
yield "wait...";
await new Promise(r=>setTimeout(r, 900));
yield new Promise(r=>setTimeout(()=>r("okay!"), 100));
}
async function main() {
for await (let item of foo()) {
let result = await item;
console.log(result);
}
}
main();
dar cu TypeScript 2.3 asta îmi dă erori:
eroare TS2318: Nu se poate găsi tipul global 'AsyncIterableIterator'. example.ts(10,26):
eroare TS2504: Tipul trebuie să aibă o metodă 'Symbol.asyncIterator' care să returneze un iterator asincron.
Cum poate fi remediată această eroare și cum poți rula generatorul asincron?
Răspuns #1
Symbol.asyncIterator este o caracteristică esnext; așadar trebuie să țintești în mod explicit esnext, sau să adaugi biblioteca esnext.asynciterable, pentru ca TypeScript să suporte sintaxa. Totuși, TypeScript nu se ocupă de implementarea simbolurilor la runtime în prezent, așa că trebuie să folosești un polyfill.
Polyfill + Compilare în jos
Adaugă "esnext.asynciterable" la lib în tsconfig.json
{
"compilerOptions": {
"target": "es2015",
"moduleResolution": "node",
"module": "commonjs",
"lib": [
"dom",
"es2015",
"esnext.asynciterable"
]
}
}
poți folosi un polyfill pentru Symbol.asyncIterator pur și simplu creând un Symbol nou înainte de a face altceva.
if(Symbol["asyncIterator"] === undefined) ((Symbol as any)["asyncIterator"]) = Symbol.for("asyncIterator");
Compilează și rulează ca de obicei.
Acest lucru ar trebui aplicat și în orice pachete reutilizabile - ideal, pe prima linie a scriptului main al modulului tău
Suport nativ
Dacă vizezi Node 7 sau versiuni mai noi, poți de fapt să rulezi iteratori asincroni nativ cu un flag.
Setați target: "esnext" în tsconfig.json, compilați și rulați cu
node --harmony_async_iteration example.js
Același lucru este disponibil și pentru ts-node, unde îl poți rula direct.
ts-node --harmony_async_iteration example.ts
Cu Node 9; a fost pus în scenă sub steagul --harmony
Începând cu Node 10; este activat implicit.
Avertisment :
Am întâmpinat unele probleme de compatibilitate atunci când am combinat codul async-gen compilat cu TypeScript cu down-compile-ul Babel într-un pachet webpack. Aceasta ar putea fi din cauza modului în care polyfill-ul Babel caută simbolul și apoi creează unul dacă lipsește. Problema de compatibilitate este că se pare că codul Babel nu consideră că codul TypeScript (+polyfill-ul Symbol) are o intrare-cheie Symbol.asyncIterable.
De asemenea, s-ar putea evita problema folosind același polyfill pentru Symbol pe care îl va folosi pluginul Babel:
import "core-js/modules/es7.symbol.async-iterator"
