An issue occurred while creating a generic MessageBus in Typescript with rxjs due to a typing mismatch

I'm currently working on developing a versatile MessageBus in Typescript. My goal is to create message classes that inherit from a main MessageBusMessage class, allowing for subscription to messages of a specific class type with strong generic typing throughout.

Here's what I have so far:

import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/filter';

export class MessageBusMessage {
}

export class TestMessage extends MessageBusMessage {
    constructor(public readonly someValue: string) {
        super();
    }
}

export class MessageBus {
    private subject: Subject<MessageBusMessage>;

    constructor() {
        this.subject = new Subject();
    }

    public publish(message: MessageBusMessage) {
        this.subject.next(message);
    }

    public getMessagesOf<T extends MessageBusMessage>(messageType: T): Observable<T> {
        return this.subject.filter( (message) => {
            return (message.constructor as any).name === (messageType as any).name;
        }) as any;
    }
}

const messageBus = new MessageBus();
const subscription = messageBus.getMessagesOf(TestMessage).subscribe(
    (message) => {
        console.log('got test message', message.someValue);
    }
)

messageBus.publish(new TestMessage('some test value'));

However, I've encountered an issue with the message subscription. The type of the message is showing as the constructor type rather than the actual object instance type, resulting in a type checking error from the Typescript compiler:

Property 'someValue' does not exist on type 'typeof TestMessage'.

It seems that the observable type is incorrect for the return type of getMessageOf. But what should the correct type be? How can I access the object instance type?

Answer №1

Instead of accepting an instance of T, make sure to declare getMessagesOf<T> as taking the constructor for T:

public getMessagesOf<T extends MessageBusMessage>(messageType: new (...args: any[]) => T): Observable<T>

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

Merge ObjectA emissions with ObjectB Array using RxJS

Currently, I have a code snippet that pulls data from a web service: @Effect() searchAction$ : Observable<Action> = this._actions$ .ofType(ActionTypes.SEARCH_CASES) .do(val => this._store.dispatch(new SetLoadingAction(true))) .map(act ...

Verify the dates in various formats

I need to create a function that compares two different models. One model is from the initial state of a form, retrieved from a backend service as a date object. The other model is after conversion in the front end. function findDateDifferences(obj1, ...

Explore all user-defined properties of a specified type using the TypeScript Compiler API

Consider the following model structure: interface Address{ country: string; } interface Author{ authorId: number; authorName:string; address: Address; } interface Book{ bookId:string; title: string; author : Author; } I want to iterate th ...

Extracting Information from a Table in Angular 7

Hi there, I'm new to this forum so if I break any rules, please let me know! I'm working with the code below in my app.component.html: <tr *ngFor="let item of items" (click)="getClient($event)"> <td> {{ item.nr }} </td> ...

The where clause in the Typeorm query builder instance is not functioning properly after its common usage

When fetching data for my relations, I opted to use QueryBuilder. In order to validate certain get request parameters before the index, I established a common QueryBuilder instance as shown below. // Common Get Query const result = await this.reserva ...

What is the best way to manage errors and responses before passing them on to the subscriber when using rxjs lastValueFrom with the pipe operator and take(1

I'm seeking advice on the following code snippet: async getItemById(idParam: string): Promise<any> { return await lastValueFrom<any>(this.http.get('http://localhost:3000/api/item?id=' + idParam).pipe(take(1))) } What is the ...

Can TypeScript interfaces be used to achieve the same functionality as an abstract class?

I am currently working on developing a function that will return an array type with custom methods, allowing me to utilize it across various sections of the application. Typically, this is achieved using Abstract Classes where abstract methods are defined ...

"The call does not have any matching overloads" - TypeScript error encountered when using react-input-mask with react-hook-forms

Encountering an issue with the code snippet below import "./styles.css"; import React from "react"; import { useForm, Controller } from "react-hook-form"; import InputMask from "react-input-mask"; import { Input } fr ...

When setting up Webpack with TypeScript, an error is encountered related to imports

Recently, I attempted to convert my Webpack configuration from JavaScript to TypeScript but encountered numerous difficulties in the process. To kick things off, I created a basic webpack configuration file with some parts missing. Here is how my webpack.c ...

NextImage's ImageProps is overriding src and alt properties

I've created a wrapper called IllustrationWrapper that I'm utilizing in different components. import Image, { ImageProps } from 'next/image'; const getImageUrl = (illustrationName: string) => { return `https://my-link.com/illustra ...

What's the best way to implement asynchronous state updating in React and Redux?

In my React incremental-style game, I have a setInterval function set up in App.ts: useEffect(() => { const loop = setInterval(() => { if (runStatus) { setTime(time + 1); } }, rate); return () => clearInterval(lo ...

Mastering Props Typing in React Using TypeScript

Currently, I am faced with the task of defining the following: interface MyCompProps { someAttr: number } Instead of having to explicitly list all the aria-* attributes I need upfront, I would like to simply use aria- and other normal HTML attributes ...

Utilizing a TypeScript getter or local variable to reference a service variable within an Angular component

Suppose you have an array of objects stored in a service export class DataService { private _dataSources : Array<DataSource> contructor(private callerService: CallerService){ this._dataSources = this.callerService.getDataSources(); // fetc ...

Definition of Redux store state object

Recently, I started using Typescript in a React/Redux project, and I am facing some confusion regarding how type definitions should be incorporated into the application state. My goal is to make a specific piece of state accessible to a container component ...

Employing the keyof operator with the typeof keyword to access an object

What data type should be used for the key variable? I am encountering an error stating that "string" cannot be used to index the type "active1: boolean, active2". const [actives, setActives] = React.useState({ active1: false, active2: false, }); con ...

The 'Icon' JSX component does not contain any construction or call signatures

I am currently learning typescript and facing an issue while working on a sidebar navigation feature. I have an array containing menu items with icons that I need to display. Here is the array: const menuItems = [ { id: 1, label: "Dashboard", icon: <Co ...

Effortless code formatting with VS Code for TypeScript and JavaScript

Does anyone know of any extensions or JSON settings that can help me format my code like this: if(true) { } else { } Instead of like this: if(true){ } else { } ...

Issue: The UserComponent is attempting to set the property 'id' of an undefined object, resulting in an error

An error has occurred indicating that the property 'id' cannot be set as it is undefined in the UserComponent file of user.component.ts. Here is the TypeScript code: import { Component, OnInit } from "@angular/core"; import { ActivatedRoute, Rou ...

Ensure that the current HTTP request is completed before re-sending the identical one in RXJS / Angular

Imagine this scenario, simplified for the community: In my angular 16 application, I have a form with various input fields such as "firstName", "surName", "phoneNumber", and more. Here is an example code snippet: <input [(ngModel)]="state.surname ...

Completing a Promise Chain with the Power of Node, MySQL, and TypeScript

I'm currently utilizing node and typescript. In my setup, there's a controller and a repository. Strangely, I am able to log data everywhere except right after the return from the repository. As a result, the controller doesn't receive any d ...