What is the method to retrieve the parameter names of a function in TypeScript?

In an attempt to create a wrapper function that takes a function as input and returns a new typed function that allows for both a list of parameters and an object containing parameter names as keys.

I have developed the following code, which functions as expected. The issue lies in the fact that I am required to pass an additional type with keys representing parameter names and their corresponding types. My aim is to achieve this dynamically, by accessing the parameter names.

//I want to eliminate the Args parameters and make it dynamic using F type.
function wrapper<F extends (...args: any) => any, Args>(func: unknown) {
   type ParametersList = Parameters<F>;
   return func as (...args: [Args] | ParametersList) => ReturnType<F>;
}
const add = (x: number, y: number) => x + y;
const wrappedAdd = wrapper<typeof add, { x: number; y: number }>(add);

The Parameters function retrieves a named tuple (a new feature, I believe). Is there a method to obtain the names/labels of that tuple? Your suggestions are welcome.

###Edit: After some investigation, I discovered that it's not possible to retrieve the parameter names of a function. Therefore, my objective now is to streamline the code. Instead of passing an object in place of Args, I prefer to simply pass an array of strings.

const wrappedAdd = wrapper<typeof add, ["x", "y"]>(add);

I intend to dynamically generate an object using this array. Thank you.

Answer №1

In my opinion, it's more beneficial to declare all types in the global scope.



type Elem = any;

type Predicate<Key extends number, Value extends Elem> = Record<Key, Value>

type Reduce<
    Arr extends ReadonlyArray<Elem>,
    Result extends Record<string, any> = {}
    > = Arr extends []
    ? Result
    : Arr extends [infer H]
    ? Result & Predicate<0, H>
    : Arr extends readonly [...infer Tail, infer H]
    ? Tail extends ReadonlyArray<Elem>
    ? Reduce<Tail, Result & Predicate<Tail['length'], H>>
    : never
    : never;


function wrapper<F extends (...args: any) => any>(func: F):
    (...args: [Reduce<Parameters<F>>] | Parameters<F>) => ReturnType<F> {
    return func
}

const add = (x: number, y: string, z: number[]) => x + y;

const wrappedAdd = wrapper(add);
const add = (x: number, y: string, z: number[]) => x + y;

const wrappedAdd = wrapper(add)({ 0: 1, 1: 'hello', 2: [1] }); // ok
const wrappedAdd2 = wrapper(add)(1, 'hello', [1]); // ok


By the way, there's no need to use type assertion here. You can eliminate the as operator altogether.

If you want more examples of such type definitions, feel free to check out my article

Here is a representation of the Reduce type in nearly pure JS:

const reduce = <T,>(arr: T[], cache = {}) => {
    if (arr.length === 0) {
        return cache
    }
    if (arr.length === 1) {
        const [head] = arr;
        return { ...cache, [0]: head }
    }
    const [head, ...rest] = arr;
    return reduce(rest, { ...cache, [rest.length]: head })
}

Playground

As @jcalz mentioned:

Parameter names are not observable in the type system except as documentation for IntelliSense

It's not possible to infer parameter names and include them in another type in TypeScript, so I opted for using index types.

Using 0 for the first argument, 1 for the second, and so on...

Regarding the use of argument names:

Docs

There is one place where the differences begin to become observable though: readability.

They’re purely there for documentation and tooling.

const add = (x: number) => x + x

type Args = Parameters<typeof add>

type Infer = Args extends [infer R] ? R : never // number
type Infer2 = Args extends [x: infer R] ? R : never // number

Therefore, it's currently not feasible in the current version of TypeScript.

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

Tips for effectively wrapping Material UI v5 component to ensure the Grow component functions correctly

Being a newcomer to React, I want to apologize in advance for any silly mistakes or inaccuracies that may be present. I have successfully implemented the code for my Blog page: export default function Blog() { const [photos, setPhotos] = useState([]); ...

Tips for setting up a popup menu when clicking a button on a webpage

I am currently working on developing a popup menu with a greyed-out background that appears when the user clicks on a button in React. My code implementation is as follows: // The ifButtonClicked function is called when another button is clicked // Some ...

Removing an item from an array within subdocuments when a nested id is located

{ "_id" : ObjectId("55a4b23636e6ba35079eb497"), "userName" : "David", "email" : "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e28683948b86a2858f838b8ecc818d8f">[email protected]</a>", "image" : " ...

When utilizing the Split function, it consistently provides an array void of any elements [such as Browserstack

Instructions for Replicating the Issue: Access any website using an IOS device on Browserstack Launch DevTools Run the command "bla bla bla".split(" ") Expected Output: (3) ["bla", "bla", "bla"] Actual ...

Node.JS AJAX request with no data payload

Encountering an issue where no data is being received on the server side from an AJAX request because the req.body is empty (console logs it as {}). script.js: $("#button").click(function(){ var number = $("#number").val(); $.ajax({ ...

Upon the initial hover, the data added to the title tag following an Ajax call is not appearing

I am currently working on an ajax request that retrieves information such as username, email, and user_id. Once the ajax call is successful, I use jQuery to append this data to the title tag. The main issue I am facing is that the data is only displayed af ...

Traverse through an array or object using recursive render functions in JavaScript

Here is an example of the issue I am currently trying to solve: https://codepen.io/wombsplitter/pen/KyWKod This is the structure of my array: [{ //obj 1 link: [{ //obj 2 link: [{ //obj 3 }] }] }] The ...

Utilizing NestJS to efficiently share an end-to-end server across multiple test suites

Currently, I'm utilizing the NestJS test module to simulate the nest app for testing purposes and my goal is to make this app accessible across various test suites. Here is how I have set it up: test |_ helpers |_ testApp.ts |_ e2e |_ u ...

Is it possible to provide an offset to the raycaster in three.js?

I am currently working on developing a pool game using three.js. As part of the gameplay, I have incorporated a helper ruler that indicates the direction of the hit. This ruler is represented by an ArrowHelper and is positioned at y=0, which aligns with ...

Uncover the reason behind the application's crash with Titanium

If we encounter non-crashing errors, utilizing LogCatcher can help by pinpointing which Javascript code is causing the issue. However, in the event of a crash, there's no time for logging Javascript errors. In such cases, integrating tools like ARCA ...

Utilize AJAX to dynamically insert data into the database

I have created a JSP page that displays records, and now I am looking to include a dynamic link or button in the JSP that allows inserting data into the database without needing to refresh the page. This link should open a pop-up window with input fields ...

Having trouble with app crashes when navigating with react-native-webview?

I've encountered an issue with react-native-webview in my code. It's being used under a scrollview and causing the app to crash when I press the back button or navigate to another screen. Here is my React Native video code snippet: <WebView ...

Tips for accessing the HTML code of a TextBox in JavaScript while utilizing HTMLEditorExtender

Currently, I am utilizing the HTMLEditorExtender ajax tool on my website. The data is being saved in HTML format into the database and then retrieved within my project without any issues. However, there is a setback that I have encountered... When attemp ...

"Encountering a Syntax Error When Using request.post in Dojo Framework on Button Click

Here are three questions to consider: 1) What strategies can be utilized to streamline this code and reduce nesting and quote-related complications? 2) Are there any suggestions for addressing the parsing error mentioned below? I've already tested sep ...

In what ways can enhancing the TypeScript type system with additional restrictions help eliminate errors?

Encountered issues while working on my TypeScript project due to errors in the type definitions of a library. The solution was to enable the strictNullChecks flag. It seems counter-intuitive that adding restrictions can eliminate errors, when usually it&a ...

Requesting Axios.get for the value of years on end

I'm grappling with obtaining a JSON file from the server. The endpoint requires a year parameter, which needs to be set as the current year number as its value (e.g., ?year=2019). Furthermore, I need to fetch data for the previous and upcoming years a ...

The uploaded files are not supported due to a media type error (415)

Although I found a similar query, it didn't provide a solution to the error I am encountering. Below is the PUT action in my API's Controller, which functions correctly in Swagger: [HttpPut("{id}/upload")] public async Task<IActionResult> ...

What is the best way to iterate over JSON data from an endpoint that contains multiple nested arrays using the .map() method?

Seeking to showcase weather API data from: () import Image from "next/image" interface Hour { time_epoch: number time: string temp_c: number temp_f: number is_day: number wind_mph: number wind_kph: number wind_deg ...

Issue with Vue.js: document.querySelector is returning a null value even though the element clearly exists

I'm currently working on implementing a responsive navbar following Kevin Powell's tutorial, but I've run into an issue. For some reason, when I try to select the element with the class 'primary-navigation' using 'const primar ...

Yet another interactive JQuery feature found within the JQuery UI Tabs framework, utilizing seamless Ajax page loading

Currently, I am using JQuery U Tabs with Ajax Page Calls. In my Pages, I have a custom scroller that is functioning correctly. Additionally, I have an ajax search table that works when the page is loaded by itself in the browser but not when called within ...