Invoke a general function with corresponding generic parameters

I am currently working on a function that takes another function and its arguments as parameters, then runs the function with the provided arguments and returns the result while maintaining the data types.

If the function being provided has a fixed return type, everything works smoothly. However, when the return type of the function is dependent on the parameters, I encounter difficulties in preserving the return type.

Below is my unsuccessful attempt which illustrates what I am aiming to achieve:

function f<A>(args: A) {
  return args
}
// Directly calling the function yields the expected output:
const result = f('test') // OK: type of result is 'test'

// I tried to explicitly define the return type but it was not successful
type ReturnTypeWithArgs<
  F extends (args: any) => any,
  A extends Parameters<F>[0],
> = F extends (args: A) => infer R ? R : never

// This is the function I want to create
function callFunction<F extends (args: any) => any, A extends Parameters<F>[0]>(
  f: F,
  args: A,
): ReturnTypeWithArgs<F, A> {
  return f(args)
}

// My goal is to have the same return type when using callFunction. Unfortunately, it does not work as intended:
const result2 = callFunction(f, 'test') // KO: typeof test2 is unknown

Answer №1

At this moment, there isn't a purely type-level method to determine the return type of a generic function when provided with a specific argument type. Using conditional type inference doesn't yield the desired result as it replaces generic type parameters with their constraints.

An open suggestion has been made for type operators that would address this issue, but it is currently marked as "Awaiting More Feedback" on GitHub without significant engagement from the community. However, users can show support by visiting the link and explaining the need and use case for such functionality.


In TypeScript, manipulating higher order generics typically involves incorporating value-level code that translates to JavaScript during compilation. A workaround involves creating a separate generic function to achieve the desired type manipulation, as demonstrated in the implementation detailed in microsoft/TypeScript#30215.

function callFunction<A, R>(f: (arg: A) => R, args: A): R {
    return f(args)
}
const result = callFunction(f, 'test') // string

This approach leads to obtaining the actual input type, like 'string', instead of just 'unknown'.


Note that there might be instances where inferred types may not match the expected literal type due to limitations in TypeScript's inference mechanism. In such cases, hints or workarounds can assist in achieving the correct narrower types, as shown in the example involving the Narrowable hint type constraint.

type Narrowable = string | number | boolean | null | undefined | bigint | {};
function callFunction<A extends Narrowable, R>(
    f: (arg: A) => R,
    args: A,
): R {
    return f(args)
}
const result2 = callFunction(f, 'test') // "test"

Link to 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

Oops! The formGroup function in Angular 5 requires an instance of a FormGroup

While working with Angular 5, I encountered an error in this basic form. Here is the issue: Error Message: EditVisitanteDialogComponent.html:10 ERROR Error: formGroup expects a FormGroup instance. Please pass one in. Example: > > &l ...

Using the Ngclass function with a pair of objects

Can you include 2 objects in an ngclass function like this? <div class="progress-bar"[ngClass]="getProgressValues(obj.val1,obj.val2)"> </div> I am encountering a JSON error. SyntaxError: JSON.parse: bad control character in string literal at l ...

Sending a parameter to a route guard

I've been developing an application that involves multiple roles, each requiring its own guard to restrict access to various parts of the app. While I know it's possible to create separate guard classes for each role, I'm hoping to find a mo ...

Karma is reporting an error with TypeScript, saying it cannot locate the variable 'exports'

Currently, I am in the process of mastering how to write Unit Test cases for an angular project coded in Typescript. To facilitate this, I have opted for utilizing Karma and Mocha. Below lays out the structure of the application: Project/ ├── app/ ...

Create a unique custom design for your Mapbox GL control

When developing the website, we utilized Angular 8, Typescript, and SCSS. We are using mgl-map to display a map, and I wanted to create a custom control for it with unique styles. I added the custom control to the map using: const centerOnCoordinatesC ...

Change the color of active buttons on dynamically generated buttons

My current challenge involves getting a button to stay active when pressed, especially when dealing with dynamically created buttons. Here is my current setup: <Grid container sx={{ padding: "10px" }}> {Object.values(CATEGORIES).map((c) => { ...

Utilize the prototype feature from a versatile source

Can a class with a generic like class Foo<A> {} access A's prototype or use a typeguard on A, or perform any kind of logic based solely on A's type - without being given the class, interface, or instance to Foo's constructor (e.g. when ...

Discover the use of dot notation for accessing nested properties

In the deps array below, I aim to enforce type safety. Only strings allowed should be in dot notation of ${moduleX}.${moduleX service} // Modules each have a factory function that can return a services object (async) createModules({ data: { factory: ...

Ways to display map results in multiple columns utilizing react

I am facing a challenge and seeking guidance on how to achieve a specific layout using React. My goal is to display results in two columns as shown below: item 1 | item 4 item 2 | item 5 item 3 | item 6 I have attempted to check the array length and dete ...

Identifying Data Types in Typescript Using a Union Type Guard

I came across this interesting type guard: enum X { A = "1" } const isNullableX = (value: any): value is X | null => false let bar: string | null = '' if (isNullableX(bar)) { console.log(bar) } Surprisingly, in the last con ...

Parentheses are automatically wrapped around the implicit return of arrow functions

Currently, I am utilizing Visual Studio Code along with Prettier, and I have noticed that the function: (token: string) => this.token = token is being transformed into: (token: string) => (this.token = token) This modification seems to decrease r ...

Utilizing Conditional CSS Classes in React Material-UI (MUI) 5

I am in the process of migrating from React material-ui 4 to MUI 5. How can I implement this particular design pattern using the new styled API (or any other suitable method)? My project is written in Typescript. const useStyles = makeStyles(theme => ...

Currently in the process of modernizing an outdated method to a more up-to-date version in Jasmine, encountering issues related to

Currently working to update the method throwOnExpectationFailure to the newer one oneFailurePerSpec. According to the Jasmine documentation, this can be achieved by: Use the `oneFailurePerSpec` option with Env#configure After conducting research, I came ...

Where's the tsconfig.json for Firebase Emulators?

I've encountered an issue with my Firebase project that's written in JavaScript (not TypeScript). When attempting to run the functions emulator, I'm getting the following error: $ firebase emulators:start --only functions ⚠ functions: Ca ...

What is the process of bringing in a Svelte component into a Typescript file?

Can a Svelte component be imported into a Typescript file and successfully compiled by Rollup? While the following code works fine as a Javascript file, it encounters errors when converted to Typescript, as the TS compiler struggles with a .svelte file: i ...

How to bring in a specific module using its name in TypeScript

Can a module in typescript import itself by its own name? For example, let's consider a module called my-module with various tests. Is it possible to import it within the tests using import ... from "my-module" instead of using a local path like impo ...

Lambda functions that support multiple languages coexisting in a single directory

As I have lambda functions written in both Typescript and Java, I am contemplating whether to store them all together in a single directory or separate them based on the language. Our infrastructure deployment is done using terraform and CI/CD with Jenki ...

Troubleshooting webpack encore issues with importing enums from node_modules

I am faced with a challenge of utilizing an enum from a library I created in a different project. The library is developed using Vue and typescript, bundled with rollup. On the other hand, the project is built with Symfony, with the front end also using Vu ...

Customize time formatting in Angular to accommodate localized time formats

I am utilizing Angular's localization service version 8.3.28 to support English, Spanish (Mexico) with code es-MX, and Spanish (Spain) with code es-SP While using the date pipe: {{ foo.Date | date: 'shortDate' }} The dates are changing to ...

Disruptions in typing occur due to errors popping up while utilizing zod and react-hook-forms within a TypeScript application

Currently, I am working on developing a registration page for users using react-hook-forms for the registration form and zod for validation. Initially, when testing the form, I noticed that errors only appeared after submitting the form. However, once the ...