Using TypeScript to Infer Types in a Wrapper Function

When it comes to functions related to database operations, I have a handy utility/wrapper function that handles specific tasks. It takes a function fn of type

Promise<PromiseReturnType<GENERIC>>
, performs some preliminary actions (such as checking for connection), and then executes the function:

// Implementation in file `A.ts`
type PromiseReturnType<T = undefined> = {success: boolean, response: T } 

const DatabaseOperation = <Fn extends (...args: any) => Promise<PromiseReturnType<Data>>, Data>(fn: (...args: any) => Promise<PromiseReturnType<Data>>) => {

    return async function (...args: Parameters<Fn>): Promise<PromiseReturnType<Data>> {
        if (!isConnected) return Promise.reject({ success: false, response: new Error("Not connected to the Database!") })

        return await fn(...args)
    }

}

This utility function is then utilized as follows:

// Usage in file `B.ts`
const dbOperation = async (myArg: number): Promise<PromiseReturnType<string> => {

    return Promise.resolve({ success: true, response: `hello world ${myArg}` })

}


export default DatabaseOperation<typeof dbOperation, string>(dbOperation)

One issue encountered is that the return type cannot be inferred accurately, resulting in Promise<any> instead of

Promise<PromiseReturnType<string>>
.

When using this wrapped function, the syntax would be as follows:

import dbOperation from "B.ts"

(function () {
   await dbOperation() // Type: dbOperation(myArg: number): Promise<any>
})()

If you have any suggestions on how to address this challenge or improve the implementation in general, your insights are greatly appreciated. Thank you!

Answer №1

So close, yet so far:



declare var isConnected: boolean;

type PromiseReturnType<T = undefined> = { success: boolean, response: T }

const DatabaseOperation = <Data, Fn extends (...args: any[]) => Promise<PromiseReturnType<Data>>,>(fn: (...args: any[]) => Promise<PromiseReturnType<Data>>) => {

    return async function (...args: Parameters<Fn>): Promise<PromiseReturnType<Data>> {
        if (!isConnected) return Promise.reject({ success: false, response: new Error("Not connected to the Database!") })

        return await fn(...args)
    }

}

const dbOperation = (myArg: number): Promise<PromiseReturnType<string>> =>
    Promise.resolve({ success: true, response: `hello world ${myArg}` })



const fn = DatabaseOperation(dbOperation)

const result = fn(42) // Promise<PromiseReturnType<string>>

Check it out on Playground

Make sure to use an array any[] for ...args, rather than just any

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 could be the underlying reason for the unusual behavior observed in this range polyfill implementation?

I am attempting to transform an HTML5 range input into a set of radio buttons. Each radio button corresponds to a value within the original range, with text displaying its value. However, I am encountering an issue where the last piece of text, meant to sh ...

Automatic resizing of line charts in Angular with nvd3

I'm currently utilizing AngularNVD3 directives. Referencing the example at: https://github.com/angularjs-nvd3-directives/angularjs-nvd3-directives/blob/master/examples/lineChart.with.automatic.resize.html <!-- width and height have been removed f ...

Is it possible to bypass the same-origin policy when creating AJAX client code for a Google AppEngine site?

I am collaborating with someone who has a Google AppEngine website with a custom API located there. My goal is to create AJAX Javascript code that interacts with the custom API on the site, but I am facing difficulties due to the same-origin policy. JSONP ...

Navigating through events within React

I'm working on creating a login page, where upon clicking the submit button it should navigate to the Dashboard page. However, I seem to be encountering an issue with my code. After entering login details and clicking on the login button, the details ...

How to include additional custom attribute in a jQuery FormBuilder

Currently, I am utilizing jQuery FormBuilder from and I am in need of a custom attribute in the form of a Checkbox for each type. Whether it is a textarea, text input, checkbox, or any other type, I would like to consistently include the same checkbox as ...

What is the process for extracting the period value from SMA technical indicators within highcharts?

Can someone assist me in retrieving the period value from SMA indicator series by clicking on the series? series : [{ name: 'AAPL Stock Price', type : 'line', id: 'primary', ...

What is the best way to display live data to multiple users with React and Firebase?

I'm working on a messaging app that needs to update in real-time. Currently, I have implemented the functionality to log in using Google, post messages, and display them on the screen. However, when another user logs in with a different Google account ...

Displaying the content of the log file within a textarea

Currently, I am working on a project that involves displaying log file contents in a text area. To achieve this, I am utilizing XML HTTP request to read the file content through a Web API. The Web API function reads the file contents as a stream and retu ...

excess white space appears in the mobile version

I recently completed a website using both materializecss and bootstrap platforms. While I know this may not be the best practice, it worked for my needs. However, I am facing an issue with the mobile view. When I reduce the viewport size, a margin appear ...

How can I place a new ThreeJS child element at the front and center of a scene?

I have been working on a webpage that is inspired by the CSS3D molecules sample from ThreeJS's library. You can check out the original sample here. In my project, I am dynamically creating new nodes (atoms) and attaching them to existing nodes. Once ...

Interactive image sliders in a Netflix-inspired style with live previews on hover, fully compatible with Bootstrap framework

I'm looking for suggestions on Twitter Bootstrap compatible jquery plugins that can create a Netflix-style continuously scrolling image carousel with mouse-over functionality. I've tried the carousel included in the Bootstrap JS library, but it r ...

Are the Angular App routerlinks functioning properly in development but encountering issues in the production environment?

Every time I execute the command npm start, my Angular application works perfectly as intended. However, when I attempt to build it in "prod" mode, my application doesn't seem to function properly. It only displays a static page. All navigation link ...

This property cannot be found on the specified type

So, I have this TypeScript function that will return one of two different objects based on the input value: function myfunc(isError:boolean): {response:string}|{error:string} { if(isError) return {error:''} return {response:''} } N ...

The differences between getElementById and getElementByClassName

When using both getElementById and getElementByClassName, I have noticed that getElementById sometimes returns null while getElementByClassName works without any issues. I wonder what might be causing this discrepancy. It is my understanding that getElemen ...

Here are the steps to calculate the duration between two dates in the specified format:

let d1 = new Date("05/20/2022 09:28:15") let d2 = new Date("05/24/2022 12:38:25") Can someone help me calculate the difference between these two dates? ...

Check out this Angular demonstration page!

Looking to demonstrate the features of my Angular page using a plugin like intro.js, however, only part of the page is shown upon loading. Users are greeted with an input box to fill out an id and submit before the rest of the page is displayed after makin ...

What could be causing my jQuery code to not function properly?

I wrote a small piece of code in jQuery, but I am having trouble executing it. Can someone help me figure out what I'm doing wrong? <html> <head> <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.2.min.js"> & ...

Angular UI.Bootstrap radio buttons behave oddly when used in conjunction with ng-repeat

Having trouble dynamically generating options for a radio model using Angular's ui.bootstrap. I attempted to ng-repeat over an array to use its contents for the btn-radio attribute as shown below: //In the controller $scope.radioModel = undefined; $ ...

Trouble with modifying style in Google Chrome and Internet Explorer prior to AJAX request

When utilizing AJAX, I have a common practice of setting up a loading indicator before each request to inform the user about the short wait. Usually, this is achieved by adding an animated loading gif. Interestingly, when performing this action in Firefox, ...

Is it accurate to consider all JavaScript code and variables as inherent properties of an execution context?

It's worth considering that everything in JS code can be viewed as a property of an execution context, whether it's a global, function, or eval() execution context. Why is this the case? Each execution context has its own unique lexical and v ...