Adjust the parameters and return types of TypeScript generic functions

Is it possible to make all the arguments of a function readonly and convert that function to an async function?

For instance:

declare function foo<T>(bar: T, baz: T[]): T;

Transform into

declare function foo<T>(bar: Readonly<T>, baz: readonly T[]): Promise<T>;

I attempted this approach, which worked for non-generic functions:

type ReadonlyArrayItems<T> = { [P in keyof T]: Readonly<T[P]> };
type MakeFunctionAsync<T> = (...args: ReadonlyArrayItems<Parameters<T>>) => Promise<ReturnType<T>>;
type Foo = MakeFunctionAsync<typeof foo>;

However, the new function type Foo alters the generic function by changing all occurrences of the original generic type T to unknown.


P.S. Thank you for the responses.

Is it feasible to apply this to all functions within an interface?

For example:

interface Methods {
    foo<T>(bar: T, baz: T[]): T;
    bar(baz: string): void;
}

Become this

interface Methods {
    foo<T>(bar: Readonly<T>, baz: readonly T[]): Promise<T>;
    bar(baz: string): Promise<void>;
}

If another type is added based on the above:

type MakeFunctionsAsync<T> = {
    [functionName in keyof T]: MakeFunctionAsync<T[functionName]>;
};

There doesn't appear to be a place to insert the generic type parameter.

type MakeFunctionsAsync<T, U> = {
    [functionName in keyof T]: MakeFunctionAsync<T[functionName]<U>>;
};

This method will not work.

Answer №1

It is recommended to include a generic parameter in the Foo:

declare function foo<A>(bar: A, baz: A[]): A;

type ReadOnlyArrayItems<A> = { [key in keyof A]: Readonly<A[key]> };
type CreateAsyncFunction<A extends (...args: any[]) => any> = (...args: ReadOnlyArrayItems<Parameters<A>>) => Promise<ReturnType<A>>;
type Foo<A> = CreateAsyncFunction<typeof foo<A>>;

Playground

If you want to convert an interface, you can use this method (make sure you have a generic interface for transformation):

type ReadOnlyArrayItems<A> = { [key in keyof A]: Readonly<A[key]> };
type CreateAsyncFunction<A extends (...args: any[]) => any> = (...args: ReadOnlyArrayItems<Parameters<A>>) => Promise<ReturnType<A>>;

interface Functions<A>{
    foo(bar: A, baz: A[]): A;
    bar(baz: string): void;
}

type MakeFunctionsAsync<A extends Record<PropertyKey, any>> = {
    [funcName in keyof A]: CreateAsyncFunction<A[funcName]>;
};

type Foo<A> = MakeFunctionsAsync<Functions<A>>;

const fooExample: Foo<string> = {
    async foo(bar, baz){
        return '';
    },
    async bar(baz){
        return;
    }
}

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

Develop a variety of Jabber client echo bots

Hello Stackoverflow Community, I've been trying different approaches to resolve my issue, but I keep ending up with stack overflow errors. Programming Language: Typescript Main Objective: To create multiple instances of the Client Class that can be ...

Using JavaScript or TypeScript to locate the key and add the value to an array

My dilemma involves an object structured as follows: [{ Date: 01/11/2022, Questionnaire: [ {Title: 'Rating', Ans: '5' }, {Title: 'Comment', Ans: 'Awesome' } ] }, { Date: 01/11/2022, Questionnaire ...

Angular 15 RouterOutlet: The Ultimate Routing Solution

I'm encountering an issue while trying to run my Angular project. X [ERROR] NG8001: 'router-outlet' is not recognized: If 'router-outlet' is an Angular component, please ensure it is included in this module. If 'router-outle ...

Issue with missing localStorage data

After saving the token in localStorage, I implemented a method to verify its correctness. Here is an excerpt from the code: let token = localStorage.getItem('token'); console.log(token); if ( !token ) { return null; } const parts = token.sp ...

Why does the server attempt to load the chart in Angular 10 Universal using Amcharts 4?

I have experience with Angular, but I am now delving into the world of using Universal for SEO purposes. My goal is to integrate a map from amcharts 4, which works fine without Angular Universal. However, I am facing an issue where the server attempts to ...

Enhancing JavaScript functions with type definitions

I have successfully implemented this TypeScript code: import ytdl from 'react-native-ytdl'; type DirectLink = { url: string; headers: any[]; }; type VideoFormat = { itag: number; url: string; width: number; height: number; }; type ...

Automatically shift focus to the next input when reaching the maximum length in Angular

Looking for a smoother way to focus the next input element in Angular without manually specifying which one. Here's my current HTML setup... <div class="mb-2 digit-insert d-flex align-items-center"> <div class="confirmation-group d-flex"&g ...

Deriving universal identifiers while modifying a data entry

This block of code showcases a function designed for compact, immutable editing of a record to assign boolean values. The function is meant to take in a record containing boolean values and a list of keys that match. The result should be a new record wher ...

The error "Property 'user' does not exist on type 'Session'." occurred while attempting to pass session data using express-session and accessing req.session.user

I'm currently working on creating a basic login form for users to access a website, where I plan to store their session data in a session cookie. The express-session documentation provides the following example for setting it up: app.post('/login ...

Utilizing Jest and nest.js for testing with absolute paths

Looking at my jest configuration inside the package.json: "jest": { "moduleFileExtensions": [ "js", "json", "ts" ], "moduleDirectories":["node_modules", "src" ...

Is my implementation of this [^{}]+(?=}) regex pattern in TypeScript accurate?

Hey there! I'm currently working on extracting values that are inside curly braces "{value}". Do you think the regular expression [^{}]+(?=}) I am using is correct? let url = "/{id}/{name}/{age}"; let params = url.match('[^{\}]+(? ...

Having difficulty combining sections of the regex to clearly define the operator precedence as intended

I am currently dealing with a regex issue in SonarQube that requires grouping to clarify operator precedence. Despite grouping the regex, it is not functioning as anticipated. SonarQube Concern: SonarQube indicates that the regex should have grouped compo ...

Edge browser experiencing issues with dispatchEvent functionality

I'm facing an issue in my Angular application where I need to open a new window and dispatch an event back to the controller. The code works fine on Chrome and Firefox, but unfortunately, it doesn't work on Edge. Here is the code snippet from th ...

What data structure is used to store HTML elements in TypeScript?

Currently, I am dealing with a typescript variable that holds the outcome of a query on the DOM: let games = document.getElementsByTagname("game"); My uncertainty lies in identifying the appropriate type for the resulting array. Should I expect an array ...

Visual Studio - Error TS1005 'Unexpected token'

After spending nearly 5 hours scouring the internet for a solution, I am still unable to resolve this persistent issue. The responses I've found so far do not seem to address the specific problem I'm facing. Although I have upgraded the tsc vers ...

Customize styles for a specific React component in a Typescript project using MaterialUI and JSS

I'm currently exploring how to customize the CSS, formatting, and theme for a specific React component in a Typescript/React/MaterialUI/JSS project. The code snippet below is an example of what I've tried so far, but it seems like the {classes.gr ...

Passing a map from the SpringBoot backend to the Angular view and storing it in LocalStorage

I'm facing a challenge with this task. I am trying to transfer a Map from my Spring Boot backend to an Angular application. Controller @GetMapping("/dict") public Map<String, String> getAll(){ return dictionaryService.getAll(); } @ ...

Ways to resolve the issue of TypeScript download file not displaying the download window

In my React application, I implemented this TypeScript code to facilitate file downloads: const handleDownloadPdf = async (pdfUrl: string) => { if (!pdfUrl) { toast.error("PDF url is null"); return; } try { ...

Exploring the Limitations of TypeScript Type Inference Using Recursive Typing

Exploring the world of Advanced Type definitions in TypeScript has been quite the challenging journey for me, as I try to experiment with different approaches. One concept I am keen on exploring is a "wizard-step-by-step" method: function fillWizardOptio ...

What is the best way to convert an array of Firestore DocumentReferences into an array of DocumentData?

Trying to create a Google Cloud Function that reads Firestore Documents from a collection and takes action based on these documents. The goal is to optimize efficiency by reading the documents once and storing them in an array to minimize read operations. ...