JavaScript/TypeScript Asynchronous Filtering on AsyncIterable<T>

I am currently working with an AsyncIterable variable and I am trying to apply a filter on it. Take a look at the example below (pseudo code) -

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);
    }
}

I am encountering an error when trying to filter on AsyncIterable - "Property 'filter' does not exist on type 'AsyncIterable'

Answer №1

Filtering a synchronous iterator is not possible, as it needs to be converted into an array first.

Currently, there is no built-in method similar to Array.from() for AsyncIterable (see pending proposal), but you can achieve it by:

async function toArray<T>(asyncIterator: AsyncIterable<T>) {
  const arr = [];
  for await (const i of asyncIterator) arr.push(i);
  return arr;
}

After that, you can apply the filter like so:

declare const items: AsyncIterable<string>;

async function foo() {
  (await toArray(items)).filter(() => true)
}

Check out the TypeScript Playground for a demo.

Answer №2

Breaking down the straightforward method:

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;
    }
}

In a similar fashion, you can create mapAsyncIterable, among others. Additionally, you may require auxiliary functions such as asyncIterableToArray and asyncIterableFirst (for obtaining the initial element).

Subsequently, your code will transform into:

class SomeClass {
    private SOME_CONST= "ABCDE";

    private async someFunction(): AsyncIterable<string> {
        return filterAsyncIterable(
            someLibrary.getAsyncItems(), 
            item => item === this.SOME_CONST,
        );
    }
}

or potentially:

class SomeClass {
    private SOME_CONST= "ABCDE";

    private async someFunction(): Promise<string[]> {
        return asyncIterableToArray(filterAsyncIterable(
            someLibrary.getAsyncItems(), 
            item => item === this.SOME_CONST,
        ));
    }
}

Answer №3

To solve this issue, you can easily create a new AsyncIterator by wrapping the original one using a generator function.

Here's a TypeScript example I put together:

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;
            }
        }
    })();
}

It's important to note that AsyncIterator is not a real type, but rather an interface that objects can adhere to by implementing a function named [Symbol.asyncIterator].

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can you match the width of a series of elements to the width of an image directly preceding the div?

Looking to ensure that a series of captions have the same width as the images preceding them. This is the HTML code: <div class="theparent"> <img src="pic.jpg"/> <div class="caption"> hello </div> <div> <div ...

Adding options to a select element using JavaScript dynamically

Is there a way to create a dynamic select list for year values using JavaScript? <form action="something"> some other fields <select id="year"> </select> </form> ...

Contrasting a string against an array

I'm having trouble comparing a string variable to elements of a string array in Visual Basic. I'm trying to compare a user-entered string to an array containing the lowercase alphabet, but my "count" variable always ends up at 25 for some reason. ...

Tips for retrieving the MenuItem name upon click event using Menu and MenuItem components in Material UI React

Utilizing MaterialUI's Menu and MenuItem components in a React project, I am looking to display the name of the menu item upon clicking on it. Upon inspecting event.currentTarget in console.log, it returns the entire list item: ListItem Image attache ...

Serialize a Python return function to JSON format

As someone who is new to JSON and Python, I'm excited to dive into the world of working with JSON in Python. Lately, I've been tinkering with some code like this: import json def product(): itemId = 84576454 itemName = 'FGX Flanne ...

The Vue BlogCards Component is missing from the display

My web app is designed to display blog posts in a grid layout. However, the BlogCards component in the Home.vue file is not showing any content as expected. The data is stored in firebase, and when I navigate to /blogs, I can see the blogs displayed in a g ...

Is it possible to integrate a personalized theme into react-dates?

Attempting to customize the styling of my react-dates DayPickerRangeController in Typescript using react-with-styles and Aphrodite. I have implemented the following code, mirroring the code found at https://github.com/airbnb/react-dates#interfaces: const ...

React Native: How come my text is breaking like this and failing to adhere to the container's margin settings?

I am facing a challenge in React Native where I need to display multiple elements next to each other, with a flex wrap when there are too many elements or if the text is too long. Each element consists of an icon and text, with the text breaking into the n ...

Encounter an Unexpected Token Issue when using NextJS-auth0 in Jest

I am facing a problem with my Next.js app that is integrated with the nextjs-auth0 package. Whenever I attempt to test a particular file and include the following import: import { getSession } from '@auth0/nextjs-auth0'; An error occurs, stating ...

Is there a way to make Bootstrap 5 load its jQuery plugins right away, rather than waiting for DOMContentLoaded?

After migrating to Bootstrap 5, I noticed that the following code is broken: <script src="https://code.jquery.com/jquery-3.6.0.js"></script> <script src="https://cdn.jsdelivr.net/npm/@popperjs/<a href="/cdn-cgi/l/email-prot ...

Obtain the identification address for a group of items

I have a JSON object containing place IDs, and I am attempting to retrieve the corresponding addresses for each ID. This is the code snippet I'm using: <div id="places" class="places"></div> <script> function initialize() { j ...

Seamless Axios operations even without internet connection in Vue.js

In my Nativescript Vue.js application, there is a functionality where the user clicks on login, Axios makes a call to an endpoint to fetch a token. However, I noticed that when the emulator phone is offline, the Axios call still goes through and the &apos ...

Exploring Angular14: A guide to efficiently looping through the controls of strictly typed FormGroups

Currently, I am working on upgrading my formGroups to be strictly typed in Angular v14. Within my FormGroup, there is a specific block of logic that iterates through all the controls and performs an action (this part is not crucial as I am facing issues be ...

Neglecting the error message for type assignment in the Typescript compiler

Presented here is a scenario I am facing: const customer = new Customer(); let customerViewModel = new CustomerLayoutViewModel(); customerViewModel = customer; Despite both Customer and CustomerLayoutViewModel being identical at the moment, there is no ...

Experiencing a 404 error after attempting to access an endpoint following a successful MSAL Azure AD

Incorporating the UserAgentApplication.loginPopup function to authenticate users on our Azure AD has been a challenge as we transition from an ASP.NET MVC application to a Vue.js front end and ASP.NET 'API' backend. The goal is to pass the access ...

Transforming a series of hex numbers into a hexadecimal array for easy reference

I'm looking to transform a char array containing formatted hex values into a hex value lookup table. For example: char crc_input[300] = "abcd12344f..."; // input unsigned char buf[4096] = { 0xab, 0xcd, 0x12, ... }; // output Here's t ...

Node.js QuickStart guide for authenticating with the Youtube API encounters error

Using node.js for a Discord bot, I encountered an issue with Google's API tutorial being outdated. Here is the link to their tutorial. The tutorial asks to select an "Other" option which no longer exists, now replaced by "desktop app". This was an ea ...

I'm attempting to arrange the movieCards in a horizontal row, but they keep stacking up vertically instead

I have created a movie list component with different attributes in the div section to display the cards in a row. However, all the cards are currently aligned in a column. Should I use flex or grid to achieve the desired layout? If so, how can I implement ...

Achieving vertical center alignment in React Native: Tips and techniques

Just a quick heads-up: This question pertains to a school project. I'm currently knee-deep in a full-stack project that utilizes React Native for the front-end. I've hit a bit of a snag when it comes to page layout. Here's the snippet of my ...

Deactivate the second subradio button when the first option is selected and vice versa

Need some assistance, hoping for your help. I have 2 choices with subcategories. 1 - Option A ---- variant 1 ---- variant 2 ---- variant 3 2 - Option B ---- variant 4 ---- variant 5 ---- variant 6 Check out my code here Users must choose betwe ...