What is the proper way to input parameters for a generic function?

I need to assign a function's parameters to a type alias. For example, consider this function:

function bar<U>(baz: U, qux: string) {}

I am trying to extract the signature of its parameters. Typically, I would do this:

type BarParams = Parameters<typeof bar>;

However, the issue arises when the signature becomes [{}, string] because the generic type U is unspecified. I attempted the following solution:

type BarParams<U> = Parameters<typeof bar<U>>; // ideally [U, string]

Unfortunately, this approach leads to multiple syntax errors. Is there a correct way to retrieve the type of a generic function's parameters list?

Answer №1

To achieve this, you can utilize the infer keyword:

type Arguments<T> = T extends (...args: infer Params) => any ? Params : never;

type Result = Arguments<(args: number, arg: string) => number >;
// Result = [number, string] 

This allows the type Params to be considered generic without explicitly declaring it like:

let fn = <T>(arg:T): T {...

playground, docs


You can also achieve generic types by specifying the function's type:

type Bar<T> = (foo: T, baz: number) => void;
type Result2<Placeholder> = Arguments<Bar<Placeholder>>; // [Placeholder, number]
type Result3 = Result2<boolean> // [boolean, number]

Answer №2

Although my solution is not an exact match for your needs, it could serve as a temporary fix.

Keep in mind that this solution is specific and works only with the foo type signature.

function foo<T>(bar: T, baz: number) { }

type Fn = (...args: any) => any
type Tail<T extends any[]> = T extends [infer _, ...infer Rest] ? Rest : never

type ReplaceFirstParameter<F extends Fn, Fst> =
    (fst: Fst, ...args: Tail<Parameters<F>>) => ReturnType<F>

type Foo<T> = ReplaceFirstParameter<typeof foo, T>

type Result = ReplaceFirstParameter<typeof foo, number> // (fst: number, baz: number) => void

This updated solution offers more generality and will replace all unknown parameters with the provided generic argument.

Please note that I make the assumption that every function's generic is unknown - which may be a weak point

type MapPredicate<T, V> = T extends unknown ? V : T

type ReplaceUnknown<
    Arr extends Array<unknown>,
    Value,
    Result extends Array<unknown> = []
    > = Arr extends []
    ? []
    : Arr extends [infer H]
    ? [...Result, MapPredicate<H, Value>]
    : Arr extends [infer Head, ...infer Tail]
    ? ReplaceUnknown<[...Tail], Value, [...Result, MapPredicate<Head, Value>]>
    : Readonly<Result>;

function foo<T>(bar: T, baz: number) { }

type Fn = (...args: any) => any

type ReplaceParameters<F extends Fn, Value> =
    (...args: ReplaceUnknown<Parameters<F>, Value>) => ReturnType<F>


type Result = ReplaceParameters<typeof foo, number> // (fst: number, baz: number) => void

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

Incorporating quotes into a unified npm script

I'm trying to merge two npm scripts into one, but the result is incorrect and causes issues with passing flags. I can't use the dotenv package, and using ampersands isn't solving the problem. Here's what I have in my package.json file ...

What is the best way to remove all selected items in a dropdown menu?

My issue pertains to Angular and Typescript. I am facing a challenging problem with a dropdown menu that has 3 items. The unique aspect is that I am not utilizing the standard select HTML tag; instead, I am using my company's custom toolkit, which ser ...

Injecting AngularJS together with TypeScript and Restangular to optimize application performance

Encountering an issue while trying to configure my angularjs + typescript application with the restangular plugin Here are the steps I have taken: Ran bower install --save restangular (now I have in index.html <script src="bower_components/restang ...

Troubleshooting problem in Grunt-TS, Grunt, watch/compile, and Dropbox integration

UPDATE: Recently, I've been experiencing some issues with another computer when it comes to watching and compiling. It seems like the tscommandxxxxxx.tmp.txt files that are generated during compilation might be causing the trouble... sometimes they ar ...

Having trouble launching the application in NX monorepo due to a reading error of undefined value (specifically trying to read 'projects')

In my NX monorepo, I had a project called grocery-shop that used nestjs as the backend API. Wanting to add a frontend, I introduced React to the project. However, after creating a new project within the monorepo using nx g @nrwl/react:app grocery-shop-weba ...

Looking to extract the expiration date from an x509 certificate?

I am currently engaged in a project that involves retrieving and displaying certificate information from an Azure integration account using Angular/Typescript. One of the requirements is to show the decoded public certificate to users to extract important ...

Change observable<object> into observable<task[]>

fetchingData(){ return this.httpClient.get('http://localhost:3000/tasks'); //The above code snippet is returning an Observable<Object>, however, I need it to be converted into an Observable<Task[]>. The Task interface correspond ...

I am looking to personalize a Material UI button within a class component using TypeScript in Material UI v4. Can you provide guidance on how to achieve this customization?

const styling = { base: { background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)', border: 0, borderRadius: 3, boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)', color: 'white', height: 48, ...

Converting <reference path/> directive to ESM import: A step-by-step guide

As I embark on developing a TypeScript application, I've reached the realization that I am not a fan of using the <reference path /> triple-slash directive. Instead, I prefer utilizing import 'something'. However, every time I attempt ...

Modifying the value of a property in an object array created using the map method is ineffective

I have a collection of objects: https://i.sstatic.net/XNrcU.png Within the collection, I wished to include an additional property to the objects. To achieve this, I utilized the map function: returnArray = returnArray.map((obj) => { obj.active = "fal ...

Typescript error: The property "Authorization" is not found in the type HeadersInit

As I utilize the npm module node-fetch, I have a helper function specifically designed to facilitate authorized requests to a third-party service. This function essentially acts as middleware by incorporating the Authorization header. async function makeAu ...

Having difficulty transferring an image file to my AWS S3 Bucket using the Azure REST API

Currently, my project is structured as follows: Frontend - TypeScript, React, fetch() for making API calls to my backend instead of using axios. Backend - C#, ASP .NET Core, Swagger UI, Azure My objective is to incorporate a basic image upload feature ...

Error TS2322: The object with properties "ready: false" and "session: null" cannot be assigned to the type "Readonly<S & withAuthState>"

Here is the interface I'm currently working with: export interface withAuthState { ready: boolean, session: any } Additionally, I have developed the following Higher Order Component (HOC): const withAuth = <P extends withAuthProps, S extends ...

Automatically pass on parameters from a universal function

If I have an object with functions that return numbers: const obj = { foo() { return 1; } bar() { return 2; } baz(num: number) { return num; } } The expected output of typeof obj would be: { foo: () => number; bar: () => number; baz ...

Experiencing a Typescript error when using the useMutation hook from react-query

I am in the process of setting up a subscription form page using next js, react-query, and typescript. However, I am encountering difficulties configuring my API request in typescript. Below is my form component: 'use client'; import React, { Fo ...

Safeguarding user data across all components is facilitated by Angular 2

My Angular2 app uses OAuth2 with password grant type for authentication. I currently store the session token on sessionStorage, but I need to securely store additional data such as user roles. While I am aware that sessionStorage or localStorage can be ea ...

Strategies for handling timeouts in TypeScript testing

When I attempt to use the calculator method to trigger the email() method, there seems to be an issue with the elements not rendering properly on the page. After waiting for a significant amount of time, a timeout error is thrown. Has anyone encountered th ...

What is the best way to prevent event propagation in d3 with TypeScript?

When working with JavaScript, I often use the following code to prevent event propagation when dragging something. var drag = d3.behavior.drag() .origin(function(d) { return d; }) .on('dragstart', function(e) { d3.event.sourceEvent ...

A programming element that is capable of accessing a data member, but mandates the use of a setter method for modifications

I am unsure whether I need a class or an interface, but my goal is to create an object with a member variable that can be easily accessed like a regular variable. For example: interface LineRange { begin: number; end: number; } However, I want th ...

Guide on creating an interface for a JSON object with an array of custom functions

I am working on developing an interface for a JSON object that consists of n keys with unknown names, each containing an array of functions with specific signatures. // CLASSES class Server { // Private variables mapping : IMapping = {} // ...