Unlock the power of TypeScript by linking together function calls

I am looking for a way to create a type that allows me to chain functions together, but delay their execution until after the initial argument is provided. The desired functionality would be something like this:

const getStringFromNumber = pipe()
    .then(add(1))
    .then(toString)
    .then(prepend('0', 5))
    .value()

To provide more context, here are the imaginary functions I will be using:

  • add is a function that takes 1 argument (a number) and returns another function which, when executed with a second argument, adds them together (e.g. add(1)(2) -> 3)
  • toString transforms an argument into a string and returns it (e.g. toString(1) -> "1")
  • prepend is a function that takes two arguments and returns another function which, when executed with a string, prepends characters to reach a minimum length (e.g.
    "1" -> "00001"
    )

In this scenario, getStringFromNumber should be a function that can be called as follows:

const result = getStringFromNumber(5)
// result is "00006"

The return value of each function does not necessarily have to be a direct value - it might be preferable to have each function return a `thenable` interface for added flexibility. However, the key point is ensuring that the final argument triggering the execution is supplied last and in the correct format.

My question is, what would be the appropriate type definition for pipe to achieve this behavior?

Answer №1

If the focus is solely on the type, the solution provided below should address the inquiry.

type Thenable<R, F> = { 
  then: <T>(fn: (arg: R) => T) => Thenable<T, F>
  value: () => (arg: F) => R
}

function pipe() {
  return {
    then: <F, T>(fn: (arg: F) => T) => { return {} as Thenable<T, F> }
  }
}

The method thenable() generates an instance of Thenable with two attributes: then and value.

then represents a generic function that takes a function fn as a parameter. The inferred return type of fn corresponds to the generic type T. This T can be utilized as the return type for then, which yields a Thenable<T>.

This ensures the accurate typing for getStringFromNumber.

const getStringFromNumber = pipe()
    .then(add(1))
    .then(toString)
    .value()

getStringFromNumber // (arg: number) => string

Playground

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

Collaborate and apply coding principles across both Android and web platforms

Currently, I am developing a web version for my Android app. Within the app, there are numerous utility files such as a class that formats strings in a specific manner. I am wondering if there is a way to write this functionality once and use it on both ...

Angular: The type AbstractControl<any> cannot be assigned to type FormControl

I am working with a child component that includes an input tag <input [formControl]="control"> component.ts file @Input() control: FormControl; In the parent component, I am using it as follows: <app-input [control]="f['email ...

NodeJS can be used to convert JSON data into an XLSX file format and allow for

I am currently working on a project in nodejs where I need to convert JSON data into XLSX format and then download it to the client's browser. I have been using the XLSX npm module to successfully convert the JSON data into a Workbook, however, I am f ...

Showcasing an input field once a specific button is pressed in an Angular application

When triggered, I am looking for a blank panel that will display a text box within the same panel. This functionality should be implemented using Angular. ...

Challenges in Power BI Custom Visual Development: Trouble setting height for div elements

Currently, I am working on creating a custom visual for Power BI that includes a leaflet map within a div element. However, the issue arises when I fail to set a specific height for the map, resulting in an empty visual. I have managed to set a fixed heigh ...

Replace i18next property type in React for language setting

We have decided to implement multilanguage support in our app and encountered an issue with function execution. const someFunction = (lang: string, url: string) => any If we mistakenly execute the function like this: someFunction('/some/url', ...

`The flaw in filtering logic - an analysis`

Looking to find matching records within two Lists. We have a List called allAnimals with attributes like animalId, and another List named domesticAnimals also containing animalId. The goal is to compare the two lists and create a new list where the anima ...

"Implemented a fresh pathway within the app-routing.module.ts file, but unfortunately, ngxAdmin is experiencing functionality issues

While customizing the ngx-admin template, I attempted to incorporate a new module into the app module and added its route in app-routing.module.ts. However, upon trying to open it, the module seems to be stuck at loading without any errors appearing in the ...

How to Merge Items within an Array of Objects Using Typescript?

I'm currently facing a challenge in combining objects from an array of Objects in typescript. The structure of the array is as follows: 0: {type: 'FeatureCollection', features: Array(134)} 1: {type: 'FeatureCollection', features: ...

Is there a way to implement hover behavior for a Material-UI Button within a ButtonGroup component?

When using MUI v5, I am encountering an issue where the first button in the code provided is only half working. The button is initially colored red (both the border and text), however, upon hovering over it, the color of the border changes to blue. This is ...

Incorporate an external library

I am currently facing a challenge in my angular2 project where I need to import a 3rd party library. Here are the steps I have taken so far: ng new myproject npm install --save createjs-easeljs npm install @types/easeljs However, I am stuck at this poin ...

What is the best way to initialize a value asynchronously for React context API in the latest version of NextJS, version

Currently, I'm working on implementing the React context API in my NextJS e-commerce application to manage a user's shopping cart. The challenge I'm facing is how to retrieve the cart contents from MongoDB to initiate the cart context. This ...

Struggling to grasp the error: "NDEFReader is not defined" in a Vue3 web application

In the process of developing a vue3 application, I am integrating the NFC Web API to facilitate reading and writing NFC Chips. My project utilizes typescript, vue routing, and pinia for smooth functionality. Everything runs smoothly when the application i ...

Is there a method or alternative solution for deconstructing TypeScript types/interfaces?

Imagine a scenario where a class has multiple type parameters: class BaseClass<T extends T1, U extends U1, V extends V1, /* etc. */ > Is there a method to consolidate these type arguments in a way that allows for "spreading" or "destructuring," sim ...

Tips for preventing the ngbTypeahead input field from automatically opening when focused until all data is fully mapped

When clicking on the input field, I want the typeahead feature to display the first 5 results. I have created a solution based on the ngbTypeahead documentation. app.component.html <div class="form-group g-0 mb-3"> <input id="typ ...

Using Two Unique Typeface Options in Material UI for ReactJS

Currently, in my React App, I am utilizing the Material UI library with Typescript instead of regular Javascript. I've encountered a small hurdle that I can't seem to overcome. The two typefaces I want to incorporate into my app are: Circular-S ...

Material-UI and TypeScript are having trouble finding a compatible overload for this function call

Currently, I'm in the process of converting a JavaScript component that utilizes Material-ui to TypeScript, and I've encountered an issue. Specifically, when rendering a tile-like image where the component prop was overridden along with an additi ...

The browser failed to display the SVG image, and the console log indicated that the promise was rejected, with the message "false."

I'm struggling to understand why my SVG isn't showing up on the screen. The console log is displaying "false," which I believe indicates that a promise was rejected Here is the TypeScript file I am working with: export class PieChartComponent im ...

Issue TS2322 presents itself when attempting to assign a value of type 'string, number, or Date' to a variable of type 'Date' after upgrading to Angular 16

I recently upgraded my project from Angular 11 to Angular 16 and encountered an issue with the DTO models generated using the NPM package "ng-swagger-gen" from the Swagger JSON file of the Web API. In my C# class on the Web API side, I have a DateTime fiel ...

Set a timeout for a single asynchronous request

Is there a way to implement a setTimeout for only one asynchronous call? I need to set a timeout before calling the GetData function from the dataservice, but it should be specific to only one asynchronous call. Any suggestions? Thank you. #html code < ...