Guide on how to connect several Subjects within an object literal to their corresponding Observables in another object literal

I am currently developing a class using Angular and I need to share multiple states associated with that class. To accomplish this, I have created several instances of BehaviorSubject

private subjects = {
    a : new BehaviorSubject<A>(this.a),
    b : new BehaviorSubject<B>(this.b),
    c : new BehaviorSubject<C>(this.c),
    d : new BehaviorSubject<D>(this.d),
    e : new BehaviorSubject<E>(this.e),
}

In order to prevent exposing the Observer side of these subjects and only make the Observable side accessible, I have kept the subjects private and exposed them as observables:

observables = {
    a : this.subjects.a.pipe(share()),
    b : this.subjects.b.pipe(share()),
    c : this.subjects.c.pipe(share()),
    d : this.subjects.d.pipe(share()),
    e : this.subjects.e.pipe(share()),
}

I believe that the process of generating observables from the subjects should be automated so that when additional subjects are added, manual adjustments to the observables are not required. This could be done in a way similar to the following:

observables = (()=>{
    let observables : {[Property in keyof typeof this.subjects]:Observable} = {}
    for(let key in this.subjects)
    {
        observables[key] = this.subjects[key as keyof typeof this.subjects].pipe(share())
    }
    return observables;
})();

The challenge here lies in defining the generic type for Observable and share. How can I overcome this issue or is there a better design pattern available?

Answer №1

From my understanding, there is no need to share the BehaviorSubject observable as it is inherently hot due to its nature as a BehaviorSubject.

To address generic typing issues, you can leverage Mapped types:

const subjects = {
  a: new BehaviorSubject<number>(1),
  b: new BehaviorSubject<string>('foo'),
  c: new BehaviorSubject<boolean>(false),
};

// define a utility type to convert BehaviorSubject<T> to Observable<T> 
type BehaviorSubjectToObservable<T> = 
  T extends BehaviorSubject<infer U> ? Observable<U> : never;

// create a type for the resulting object that maps keys to Observable<T>
type Observables<T> = {
  [P in keyof T]: BehaviorSubjectToObservable<T[P]>;
};

// transform the object using reduce function
const observables = Object.entries(subjects).reduce(
  (acc, [key, subject]) => ({ ...acc, ...{ [key]: subject.asObservable() } }),
  {} as Observables<typeof subjects>,
);

// typeof observables.a = Observable<number>
// typeof observables.b = Observable<string>
// typeof observables.c = Observable<boolean>

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

What is the best way to set up an empty {[key: string]: string} object in TypeScript?

interface a { d: {[key: string]: string} } class a { d = {} } The error message returned is as follows: Subsequent property declarations must have the same type. Property 'd' must be of type '{ [key: string]: string; }', but ...

Typescript enhances Solid JS by using the "as" prop and the "component" prop

Hey there, I've been experimenting with solid-js lately and I'm facing a challenge integrating it with typescript. My objective is to make my styling more modular by incorporating it within my components. type RelevantTags = Exclude<keyof ...

Troubleshooting the "invalid configuration" error when using Angular CLI to create a new app

While attempting to develop a new application with angular CLI, I continuously encounter the "invalid configuration" error. This same error pops up when executing the ng --version command. $ ng new angular_organicstore An invalid configuration file was fo ...

Issue regarding custom CSS implementation in Angular project

Being a French speaker, I apologize in advance for any mistakes I might make. I am also fairly new to Angular, so if you could provide detailed explanations in your responses, it would be greatly appreciated. Thank you. I am trying to import a custom CSS ...

Tips for creating a responsive swiper slider in an Angular project

In my Angular project, I am using a swiper slider with 4 items in desktop view. However, I would like to display only 1 item in the mobile view. You can see the code at this link: https://stackblitz.com/edit/ngx-swiper-wrapper-demo-h9egdh?file=app/app.com ...

Displaying [object Object] in Angular Material datatable

I am currently working on implementing a datatable component using Express and Firebase DB. Below is the service request data: getText() { return this.http.get<nomchamp[]>(this.url) .map(res => { console.log(res); return res }); ...

What are the circumstances under which JavaScript GCP libraries return null values?

My current project involves working with GCP and Firebase using typescript. I have been utilizing the provided libraries, specifically version 8 of Firebase, and have encountered some unexpected behavior. For instance (firebase, ver. 8.10.1) import 'f ...

An error occurs when attempting to access a property that does not exist on type 'never'. Why is this considered an error rather than a warning?

I am experiencing an issue with the following code snippet: let count: number | undefined | null = 10; count = null; let result: string | undefined | null = count?.toFixed(2); console.log(`Result: ${result}`); The error message I received is as follows: ...

Zero's JSON Journey

When I make an HTTP request to a JSON server and store the value in a variable, using console.log() displays all the information from the JSON. However, when I try to use interpolation to display this information in the template, it throws the following er ...

Discover an alternative to Events by harnessing the power of Observables to effectively listen for dismiss events in Angular Ionic

Currently, I am utilizing Ionic's inline modal feature that is activated by a boolean value. However, after the modal is closed, the boolean does not automatically reset to zero. The Ionic documentation suggests that developers should monitor the ionM ...

Mapping an array of keys to an array of properties using Typescript

Is there a way to achieve the following: type A = { a: string; b: number; c: boolean }; type B = ["b", "a"]; type C = MapProps<A, B> ?? // [number, string] The solution I have currently is: type C = {[key in B[number]]: A[key]} ...

Sharing information between components in Angular 4 and .NET Core applications

I am new to Angular and .NET Core. I have successfully created a web api using .NET Core, which is called from an Angular 4 application. Currently, everything is working smoothly. However, after submitting a form that inserts records into the database, I w ...

Using a universal class URL for all components in Angular 6: Tips and tricks

One common class is imported in all components with a common URL, but the URL appears to not be working. How can I create a common URL for all components in Angular so that changes need only be made in the common class in the future? export class CommonCl ...

What could be causing the sluggish performance of my protractor test cases?

I'm a beginner with Protractor. Utilizing Protractor and Jasmine for end-to-end automation testing on an Angular4 application. Noticed that when running a specific suite, it performs quickly. However, running all suites takes considerably longer to fi ...

Whenever a file is chosen, I aim to generate the video HTML dynamically and display the video with play functionalities using Angular 2 and TypeScript

I am attempting to allow users to select a video file and display it so they can play it after choosing the file. Below is my HTML code: <br> <input type="file" (change)="fileChangeEvent($event)" placeholder="upload file..." class=" ...

TypeScript Generics: Property types do not match (the properties listed are missing)

In the code snippet below, I've defined an interface, type, and a function. interface ActionWithGeneric<T> { type: 'add' | 'remove'; data: T; } type StateWithGeneric<T> = Array<ActionWithGeneric<T>> ...

Tips for resolving the "trim" of undefined property error in Node.js

Looking to set up a basic WebAPI using Firebase cloud functions with express and TypeScript. Here's the code I have so far: import * as functions from 'firebase-functions'; import * as express from 'express'; const app = express( ...

How to Implement checked radio buttons in Angular 2 using ngModel

When generating radio buttons in Angular, I am using the following code: <div class="radio" *ngFor="let gender of genders"> <input type="radio" name="gender" [checked]="gender=='male'" [value]="gender"> {{gender}} </div> ...

Creating Unique Layouts for Specific Routes in Next.js App Router

Issue with Layout Configuration I am facing a challenge in creating a unique layout for the /api/auth/* routes without including the components CustomNavbar and Footer from the main RootLayout. Despite my attempts, the main layout continues to be displaye ...

Error encountered when utilizing Meteor in conjunction with TypeScript

Currently, I am in the process of building a web application using Meteor and TypeScript within the Nitrous.io cloud development environment. After installing the TypeScript compiler, I integrated TypeScript libraries from https://github.com/meteor-typesc ...