Understanding the Purpose of the Pipe Function in Angular 2 and Typescript Observables

Recently, I encountered a situation where I needed to accept an Observer parameter in a function written in Typescript. I struggled to find a solution, reminding me of working with a delegate parameter in C#. The specific scenario involved adding a bookend for subscriptions to implement an AOP-like functionality. Although this detail is not crucial.

To make it functional, I had to modify the function parameter by appending a | character, resulting in:

(observer: Observer<any> | ((value: any) => void)): void

My question pertains to the purpose of the bolded section in the function signature. Despite extensive research, I have not been able to comprehend its significance. Initially, without the additional segment after the |, I received an error:

Argument of type '(res: any) => void' is not assignable to parameter of type 'Observer'. Property 'next' is missing in type '(res: any) => void'.

However, upon including the pipe character and the following segment, I could successfully subscribe in the traditional observer manner (using an arrow function). All subscriptions functioned as expected, eliminating the possibility of the segment after the pipe being a default value. Any insights on this would be greatly appreciated, as it is frustrating to witness something work effectively without understanding the underlying mechanism!

Answer №1

As mentioned by @echonax, it means OR as @Rob noted, it's a Union Type

Despite my slow pace, I decided to continue rather than discard what I've started :)

Initially, you limited your method to only accept Observers

class SubscribeMe<T> {
    observable: Observable<T>;
    susbscribe(observer: Observer<T>){
        return observable.susbscribe(observer);
    }
}

Then, you attempted to use an Action-like signature with it, where Action is defined as:

    type Action = <T>(t:T)=> void     

By trying:

    susbscribeMe = new SubscribeMe<any>();
    susbscribeMe.susbscribe((x)=> console.log(x));

Unfortunately, this did not match the previous signature.

Subsequently, you added an Action-like signature to the method

 class SubscribeMe<T> {
    observable: Observable<T>
    susbscribe(observer: Observer<T>| (x)=> void ){
        return observable.susbscribe(observer);
    }
}    

or...

 class SubscribeMe<T> {
    observable: Observable<T>
    susbscribe(observer: Observer<T>| Action<T>){
        return observable.susbscribe(observer);
    }
}

By doing this, you informed TypeScript that it can be called with an Action or an Observer

... and all of this is possible because the Rx.Observable interface (rxjs/Observable.d.ts)

has an overloaded signature for "subscribe" as follows:

 *  subscribe(): Subscription;
 *  subscribe(observer: PartialObserver<T>): Subscription;
 *  subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription;

This means you can subscribe with:

  • an Action
  • an Observer
  • or Null/Nothing/Nada

but will always receive a Subscription in return

For example:

import * as Rx from "rxjs";

export class SubscribeMe<T> {

    private _events = new Rx.Subject<T>();
    
    /** 
    * Hide the source of the observable  
    * */
    get events(): Rx.Observable<T> { return this._events.asObservable(); }

    /**
    *  Accept any signature accepted by Rx.Observabe INTERFACE (rxjs/Observable.d.ts)
    *  subscribe(): Subscription;
    *  subscribe(observer: PartialObserver<T>): Subscription;
    *  subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription;
    * 
    * as in OR Action<Ievent> Or Observer<Ievent> Or Null/Nothing/Nada
    */
    subscribe = (observer?: (e:T) => void | Rx.Observer<T>) => {
        return this.events.subscribe(observer);
    }
}

Answer №2

When it says the observer is of type Observer<any>, it means that the observer is capable of handling any type of data.

Alternatively, the observer could also be a ((value: any) => void) function: This is a function that takes any type of value as input and returns nothing.

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

Using React with Typescript: What is the best way to implement useMemo for managing a checkbox value?

I am currently developing a to-do list project using React and Typescript. At the moment, I have successfully implemented the functionality to add new to-do items via a form and delete them individually. Each item includes a checkbox with a boolean value. ...

What is the best way to manage data types using express middleware?

In my Node.js project, I am utilizing Typescript. When working with Express middleware, there is often a need to transform the Request object. Unfortunately, with Typescript, it can be challenging to track how exactly the Request object was transformed. If ...

Angular Error: Property 'map' is not found in type 'OperatorFunction'

Code: Using map and switchMap from 'rxjs/operators'. import { map, switchMap } from 'rxjs/operators'; Here is the canActivate code for route guard: canActivate(): Observable<boolean> { return this.auth.userObservable ...

How can I use a custom pipe from an Angular library in my project?

I am encountering a problem when trying to import a custom pipe from an Angular library into the main app. This pipe is part of a custom library and I am using the static forRoot approach to load the library's module. I have declared and exported the ...

Are event handler props in Typescript Polymorphic React Components being misassigned?

After making some adjustments, I enhanced the code to improve its readability. interface ModifiedProps<T extends ElementType> { as?: T; } type UpdatedProps<T extends ElementType> = ModifiedProps<T> & ComponentPropsWithoutRef<T ...

How can you partially update an entity in TypeORM using a query runner?

Updating a user's name partially is simple with the repository save method: await this.repository.save({ id: 1, name: 'john' }); However, when attempting to do the same using queryrunner, all fields must exist which throws an error stating ...

Efficiently Handling Multiple File Uploads using Angular and Multer

I'm seeking guidance on integrating multer (nodeJS) with Angular 7. Despite trying several solutions, I am unable to successfully upload any files. In my case, the files originate from a ReactiveForm: <mat-tab label="Documents" for ...

Error: The method that was custom created is not functioning as expected

I am working on a project where I have a collection of hero buttons that come with a customized animation which is defined in the button.component.ts file. These buttons start off as inactive, but when one is clicked, it should become active. To achieve th ...

Issue with Angular2 wysiwyg component failing to submitThe Angular2

I'm currently in the process of familiarizing myself with angular2 by developing a sleek wysiwyg component. However, I seem to have reached an obstacle at this point. Below is the code I've been working on: The form that I am utilizing for testi ...

Obtaining the date input value from the ng2-date-picker component in Angular2

I am struggling to extract the value from a date picker input field (ng2-date-picker). Despite attempting various methods to retrieve the value, I have not been successful. For reference, here is the link to the npm package I am utilizing. This represent ...

Dynamic Assignment of Object Values Based on Enum Keys in Typescript

Check out this TS Playground for this piece of code. Dynamically Assigning Object Values Based on Enum Key I am attempting to achieve the following: in the interface iAnimals, each animal key in the enum Animals should have its associated interface value, ...

The type of props injected by WithStyles

When working on my class component, I utilize material UI withStyles to inject classes as a property. export default withStyles(styles)(myComponent) In this process, const styles = ( (theme:Theme) => createStyles({className:CSS_PROPERTIES}) I am att ...

Using Typescript with AWS Lambda can sometimes be a bit tricky. For example, when trying to invoke your Lambda function locally using "sam local invoke", you might encounter an error stating

Attempting to deploy an AWS Lambda function using the sam command with AWS's Hello World Example Typescript template, but encountering issues with the example template. Suspecting a bug within AWS causing this problem. This issue can be easily repli ...

Guide to setting a default value for a select option in Angular 2+

I am having trouble setting a default option in my select box using the html selected property. I want the selected option to be assigned to StartingYear, but currently it's not working as expected. <select [(ngModel)]="StartingYear"> < ...

In Angular, how do outputs impact parents when data consistently travels down from the root?

I have a question that may seem simple, but I am really trying to understand unidirectional data flow in Angular thoroughly. If change detection always happens from top to bottom, how does @Output impact a parent component? Could I be mistaken in my assu ...

Issue Report: Angular 2 version 2.0.0-rc.1 error - Missing 'map' property on type 'Observable<Response>' differs from previous reports

It seems like I am encountering a similar issue as mentioned in Angular 2 beta.17: Property 'map' does not exist on type 'Observable<Response>' However, the solutions provided for the beta version do not seem to work for the latest r ...

Is it advisable to prevent Set and Map from having unspecified generics in TypeScript?

Upon reviewing some old code that I wrote, I realized that I had neglected to specify a generic type for a Set. The type was set as Set<unknown>. Strangely, despite this, I found that I could still utilize all the methods of the Set without encounter ...

In the process of developing a custom Vue component library with the help of Rollup and VueJS 3

My goal is to develop a custom Vue component library using rollup and Vue.js. The process went smoothly with Vue2, but I encountered issues parsing CSS files with Vue3. To address this, I updated the dependencies in the package.json file. package.json { ...

Issue with running ng serve command with proxyconfig.json file is unresolved

I am currently in the process of developing an application using the MEAN stack. Part of my strategy involves utilizing a Proxy config file to facilitate communication with the backend, which is developed in Node JS. proxyconfig.json { "/api/*": { ...

Developing a Data Generic State Management System in Angular using TypeScript

Implementing a Generic StateManagierService that can handle any type, allowing users to receive new state and data upon state change. However, something seems to be missing. export class StateManagierService<T> { private _state$: BehaviorSubject< ...