Convert a generic observable list to a generic list

Can an array containing

[Observable<string>, Observable<number>]
be converted to [string, number] using generics?

function example(obs: Observable<any>[]): any[] { }

Intended Outcome:

example(of(''), of(0)) // should return [string, number];

I am aware that rxjs uses ObservedValueOf<O> and function overloading for combineLatest, but I prefer not to use the same approach for overloading.

Answer №1

It might be a good idea to update the call signature for example() using a mapped type applied to an array:

declare function example<T extends any[]>
    (...obs: { [K in keyof T]: Observable<T[K]> }): T;

In this case, the type T corresponds to the output array/tuple type, and the input parameter obs maps T so that each element is encapsulated within Observable<>. Thanks to inference from mapped types, T can automatically be deduced from the type of obs when you invoke example():

const result = example(of(''), of(0));
// const result: [string, number]

This should give you the desired type.


Keep in mind that although the question doesn't specifically address the implementation details, there may be potential issues down the line. While I'm no rxjs expert, it appears that converting an Observable<X> to an X synchronously could pose challenges because the observable might not have a value of type

X</code available immediately upon calling <code>example()
. One approach could be to have example() throw an error if the inputs lack ready values. Alternatively, it might make more sense for example() to transform
[Observable<string>, Observable<number>]
into
Observable<[string, number]>
, where the output observable waits until each input has a value before emitting. Just something to keep in mind.


Code playground link

Answer №2

One effective approach is to combine functions that work with arrays of Observables, such as combineLatest or forkJoin, along with the toPromise method of Observable and async/await syntax. Here's a sample code snippet:

async function customExample<A, B>(observables: [obs1: Observable<A>, obs2: Observable<B>]) { 
  return combineLatest(observables).toPromise()
}

const observable1 = of('')
const observable2 = of(1)
async function runTest() {
  const result = await customExample([observable1, observable2])
}

In this example, the variable result would have the type [string, number].

It's important to note that transforming Observables (which are continuous streams) into Promises is generally not recommended.

Observables are designed to be subscribed to, where you provide up to three functions - one for handling emissions (next), one for error handling (error), and one for completion handling (complete). This is the recommended way to use Observables effectively.

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

Dealing with errors in Next.js 13 with middleware: a comprehensive guide

My attempt to manage exceptions in Next.js 13 using middleware is not producing the desired results. Below is my current code: import { NextRequest, NextFetchEvent, NextResponse } from "next/server" export function middleware(req: NextRequest, e ...

JavaScript generic type for the superclass

Is it possible to create an extendable parent class with a generic type in JavaScript, similar to how it's done in Java? public class Parent<T> { private T t; public T get() { return t; } ... If so, what would the child class l ...

Creating a multipart/form-data POST request in Angular2 and performing validation on the input type File

I am working on sending an image (base64) via a POST request and waiting for the response. The POST request should have a Content-Type of multipart/form-data, and the image itself should be of type image/jpg. This is what the POST request should look like ...

Retrieving properties of a universal function

I am facing a challenge in creating a class that accepts a factory function as one of its parameters in the constructor, which is then used to create instances of another class. The implementation below is written in JavaScript. // item to create class Ite ...

The collaboration of React hooks, typescript, mongoose, express, and socket.io in perfect harmony

I am currently working on setting up a frontend React app to communicate with a NodeJS Express API using socket.io import React, { useEffect, useState } from "react"; import io from "socket.io-client"; const socket = io("http://lo ...

Using a method call instead of a property for the ngFor directive can lead to an infinite loop of loading

Within my template, I have included the following code: <a *ngFor="let item of navItems" [routerLink]="item.link" routerLinkActive="active" class="navigation-item" [ngClass]="{'enabled': item.enabled}" > <span class="color ...

What is the best approach to develop a React Component Library adorned with Tailwind CSS and enable the main project to easily customize its theme settings?

Currently, I am in the process of developing an internal component library that utilizes Tailwind for styling. However, a question has arisen regarding how the consuming project can incorporate its own unique styles to these components. Although I have th ...

Error in Typescript SPFx: The property 'news' is not found in the type 'Readonly<{}>'

Currently, I am working on developing a spfx react component to showcase an RSS feed in the browser. My prototype is functional in a test environment, however, as spfx utilizes TypeScript, I am encountering a type error that I am unsure how to resolve. Rs ...

What is the best way to find the beginning and end of the week using Moment.js?

Is there a way to retrieve the date of the first day of the week and the date of the last day of the week using Moment.js? I am looking to fetch the dates from the start of the week until the end of the current week based on the current day in Moment.js. ...

The GET Request made for an Image in an Angular Component results in a 404 error message indicating

I have been working on uploading and fetching images from my mongodb database. Utilizing multer for the image uploads, along with express and mongoose for handling GET/POST requests has been successful so far. The process involves uploading the image to th ...

Typescript compilation fails to include require statements in certain files

Currently, I am in the process of converting a Node.js project to TypeScript. The first two main files of the Node project transpiled correctly, but the third file ran into issues with the requires statement at the top for pulling in dependencies. Despite ...

What are the various methods of specifying function types in TypeScript?

I've noticed that in Typescript you can easily declare a function type using the declare keyword. For example: declare function test1(name: string): true const t1 = test1('t') // true Alternatively, you can also use the arrow notation: c ...

How to implement the connect function in an Angular 2 table

Topic: Angular Material 2 implementation of md-table UI using cdk-table Problem: Unable to trigger connect method after a user-initiated HTTP call receives a response Approach: Create a hot observable from a behavior subject in a service. The parent c ...

Mastering Typescript lookup types - effectively limit the properties included in a merge operation with the Partial type

Exploring lookup types, I'm interested in creating a safe-merge utility function that can update an entity of type T with a subset of keys from another object. The objective is to leverage the TypeScript compiler to catch any misspelled properties or ...

How can I fix the error "Type '() => void' does not have property 'push'" in Typescript for Angular 10?

I encountered an issue while using push() on an array in an Angular 10 project written in Typescript. Error Property 'push' does not exist on type '() => void'.ts(2339) I need assistance in understanding why this error is occurring ...

Intellisense not working with express

After using the command npm install --save @types/express to install, I imported in my ts file as follows: import * as express from "express"; var app = express(); Despite this setup, I am not able to get intelisense on the app variable. Additionally ...

The UploadFile Interface seems to be missing

Can someone clarify whether the @UploadedFile decorator's interface is predefined or if I need to define it myself? ...

Typescript's forEach method allows for iterating through each element in

I am currently handling graphql data that is structured like this: "userRelations": [ { "relatedUser": { "id": 4, "firstName": "Jack", "lastName": "Miller" }, "type": "FRIEND" }, { "relatedUser": ...

Utilize NgRx's dispatch method to pass a payload and update the store

Exploring the world of ngRx is a new journey for me. I am currently in the process of establishing a store that will receive updates triggered by actions from components. NgRx create methods are being utilized to craft actions and reducers for this purpose ...

How to Link an Observable Array to Another in Angular 2

In my Angular 2 project, I am trying to chain multiple HTTP calls together. Initially, I retrieve an array of environments with one call. For each environment, I want to make another call and create objects like firstObject[{name:"name",secondObject[stuff ...