Reputation: 2168
I have a variable of type AsyncIterable. I want to filter on it, for example (psuedo code below) -
class SomeClass {
private SOME_CONST= "ABCDE";
private async someFunction(): Promise<string> {
const items: AsyncIterable<string> = await someLibrary.getAsyncItems(); // this library's function returns type of AsyncIterable<T>
return items.filter(item => item === this.SOME_CONST);
}
}
How can I filter on AsyncIterable? I get the error - "Property 'filter' does not exist on type 'AsyncIterable'
Upvotes: 0
Views: 631
Reputation: 4002
Spelling out the direct approach:
export async function* filterAsyncIterable<T>(
iterable: AsyncIterable<T>,
predicate: (t: T) => boolean,
): AsyncIterable<T> {
for await (const item of iterable) {
if (predicate(item)) yield item;
}
}
Similarly, you can write mapAsyncIterable
, etc. and you will also probably need other helpers like asyncIterableToArray
and asyncIterableFirst
(to get the first element).
Then, your code becomes:
class SomeClass {
private SOME_CONST= "ABCDE";
private async someFunction(): AsyncIterable<string> {
return filterAsyncIterable(
someLibrary.getAsyncItems(),
item => item === this.SOME_CONST,
);
}
}
or possibly:
class SomeClass {
private SOME_CONST= "ABCDE";
private async someFunction(): Promise<string[]> {
return asyncIterableToArray(filterAsyncIterable(
someLibrary.getAsyncItems(),
item => item === this.SOME_CONST,
));
}
}
Upvotes: 1
Reputation: 3787
Just create another AsyncIterator
that wraps original one using generator function.
I made a example for TypeScript:
export function filterAsyncIterator<T>(origin: AsyncIterableIterator<T>, predicate: (element: T) => boolean): AsyncIterableIterator<T> {
return (async function* () {
for await (const each of origin) {
if(predicate(each)){
yield each;
}
}
})();
}
AsyncIterator
is not an actual type. It is an interface that objects can comply by owning a function with named as [Symbol.asyncIterator]
.
Upvotes: 0
Reputation: 54708
You can't filter on a synchronous iterator either, you'll need to it convert it to an array.
At the moment there is no method like Array.from()
for AsyncIterable
(pending proposal) but you can do following :
async function toArray<T>(asyncIterator: AsyncIterable<T>) {
const arr = [];
for await (const i of asyncIterator) arr.push(i);
return arr;
}
then you can do
declare const items: AsyncIterable<string>;
async function foo() {
(await toArray(items)).filter(() => true)
}
Upvotes: 1