What is the best way to implement function chaining in TypeScript?

I'm interested in implementing function chaining in typescript.

Let's consider a sample class:

export class NumberOperator {
  private num;

  constructor(initialNum) {
    this.num = initialNum;
  }

  public add(inc = 1) {
    this.num += inc;
  }
}

Using the class as (1):

let finalNumber = new NumberOperator(3);
console.log(finalNumber); // Output: 3

Using the class as (2):

let finalNumber = new NumberOperator(3).add();
console.log(finalNumber); // Output: 4

Using the class as (3):

let finalNumber = new NumberOperator(3).add().add();
console.log(finalNumber); // Output: 5

Using the class as (4):

let finalNumber = new NumberOperator(3).add().add(2).toString();
console.log(finalNumber); // Output: "6"

I would appreciate any guidance on achieving this. Thanks in advance :)

Answer №1

To create a chainable function, simply return this from the functions you wish to chain together.

class numbOp {
    private n: number;
    constructor(num: number) {
        this.n = num;
    }

    public add(inc = 1) : this { // annotation not necessary added to address comments
        this.n = this.n + inc;
        return this;
    }
    toString() { 
        return this.n;
    }

}
let finalNumber = new numbOp(3);
console.log(finalNumber + "") // Output: 3

// How to use it with one addition
let finalNumber2 = new numbOp(3).add();
console.log(finalNumber2 + "") // Output: 4

// Using it with two additions
let finalNumber3 = new numbOp(3).add().add();
console.log(finalNumber3 + "") // Output: 5

// Using it with three additions and converting to string
let finalNumber4 = new numbOp(3).add().add(2).toString();
console.log(finalNumber4) // Output: "6"

Edit

For better output in the console:

  1. Override toString method for string representation of the object
  2. Always call toString at the end of the chain
  3. Override valueOf method and use unary + operator (for binary operations)

Example for the last option:

class numbOp {
    private n: number;
    constructor(num: number) {
        this.n = num;
    }

    public add(inc = 1): this { 
        this.n = this.n + inc;
        return this;
    }
    valueOf() { 
        return this.n;
    }

}

let finalNumber2 = new numbOp(3).add();
console.log(+finalNumber2) // Output: 4
console.log(1 + (+finalNumber2)) // Output: 5
console.log(1+(finalNumber2 as any as number)) // Output: 5

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

Is there a way to determine the remaining time or percentage until document.ready is reached?

My usual approach is to display a loading animation like this: $('#load').show(); $(document).ready(function(){ $('#load').hide(); }); where the <div id="load"> contains just an animated gif. However, I've been conside ...

I'm new to Angular, so could you please explain this to me? I'm trying to understand the concept of `private todoItems: TodoItem[] = []`. I know `TodoItem` is an array that

//This pertains to the todoList class// The property name is todoItems, which is an array of TodoItem objects fetched from the TodoItem file. I am unable to make it private using "private todoItems: TodoItem[] = []," is this because of Dependency Injectio ...

How do I specify a unique directory for pages in Next.js that is not within the src or root folders?

I'm currently facing an issue when trying to set a custom directory in Next JS. Although the default setup dictates that the pages directory should be located at the root or within the src directory, this arrangement doesn't fit my requirements ...

In Chrome, it seems like every alternate ajax request is dragging on for ten times longer than usual

I've been running into an issue with sending multiple http requests using JavaScript. In Chrome, the first request consistently takes around 30ms while the second request jumps up to 300ms. From then on, subsequent requests alternate between these two ...

Tips for implementing an autoscroll feature in the comments section when there is an abundance of comments

Having a large number of comments on a single post can make my page heavy and long sometimes. This is the current layout of my post comment system: Post 1 Comment for post 1 //if comments are more than 3 <button class="view_comments" data-id="1">Vi ...

Determine the height of an image using JavaScript

How can I retrieve the height of an image in a JavaScript function? When I use the code: var image_height = $(image).height(); The value of image_height is 0, even though my image definitely has non-zero height. Is there a different method to accurately ...

Is it possible to modify the host header within an Angular app?

I'm experiencing a vulnerability issue and to resolve it, I need to utilize SERVER_NAME instead of the Host header. Is it possible to accomplish this using Angular? ...

Tips for showcasing images retrieved from a REST API on the frontend, with the condition that only one image should be displayed using multer

I am experiencing an issue where only the image logo is being displayed in my frontend, rather than the entire image that I uploaded in string format on my backend. Can someone please help me troubleshoot this error and identify what may be wrong with my c ...

Is there a method I can use to transform this PHP script so that I can incorporate it in .JS with Ajax?

I have a JavaScript file hosted on domain1.com, but in order for it to function properly, I need to include some PHP code at the beginning. This is necessary to bypass certain restrictions on Safari for my script by creating a session. The PHP code establi ...

Selenium on Sauce Labs does not successfully load the page in Firefox after clicking

An issue has arisen where a test that functions properly with selenium webdriver locally is timing out when executed remotely on saucelabs.com. Notably, the test runs smoothly for Chrome in both local and remote scenarios. The problem seems to lie in the ...

Bringing in additional elements, ensure that there is only a single main root element

Apologies for the beginner question. I am facing an issue while trying to display a .vue file with parent and children components, resulting in a "more than one root element" error. It seems strange to me because the imported components are supposed to be ...

Stop users from saving the page in Next.js

I'm currently working on a NextJs project that involves building an editor application. I want to ensure that the editor functionality does not work when users attempt to save the page in a different format, similar to how applications like Youtube an ...

Tips for stopping links in iOS web applications from launching in a new Safari tab

I am in the process of developing an HTML application specifically for iPads. To enhance user experience, I have added the web app to the homescreen using the "favorite" option. However, I encountered an issue where every internal URL opens in a new Safari ...

What is the most effective way to identify mobile browsers using javascript/jquery?

As I develop a website, I am incorporating image preloading using JavaScript. However, I want to ensure that the preload_images() function is not called for users on slow bandwidth connections. In my experience, the main demographic with slow internet spe ...

Dealing with illegal characters, such as the notorious £ symbol, in JSON data within a JQuery

I'm encountering an issue with a textarea and the handling of special symbols. Specifically, when I use $('#mytextarea').val() to retrieve text that contains '£', I end up seeing the black diamond with a question mark inside it. T ...

jQuery click() function fires twice when dealing with dynamic elements

I am loading content from a database through ajax into a div and then when clicking on any of these content pieces, it should reload new content. The ajax request is initialized as a method within a class that I call at the beginning: function Request(ta ...

Ways to include x-api-key in Angular API request headers

I am attempting to include the x-api-key header in the headers, as shown below: service.ts import { Injectable } from '@angular/core'; import { Http, Headers, RequestOptions, Response } from '@angular/http'; import { Observable } from ...

Disable setTimeout in Node.js triggered by an event

I am facing a dilemma with my code that constantly polls a service and I am looking for a way to efficiently cancel the interval using `clearTimeout` through events. The timeouts essentially act as intervals by calling setTimeout again within the function. ...

What could be causing the issue where only the latest data is being shown

When I use ajax to retrieve data from my database, the console.log displays all the results correctly, but in my HTML, only the last result is shown. What could be causing this issue? Any help would be appreciated! Thanks! Please keep your response simple ...

Why is the imported package not being recognized in the namespace declaration of my Node.js TypeScript file?

Currently, I am utilizing the WebStorm IDE developed by JetBrains to modify a TypeScript file within a Node.js v8.6.0 project. The JavaScript version set for this project is JSX Harmony. In the beginning of the TypeScript source file, there is an import st ...