Switching between different types of generic functions in typescript

Is there a way to convert between these two types of generic functions:

type Foo=<S>(a: S) => S
type FooReturnType = ReturnType<Foo>          // unknown

type Bar<S> = {
  (a: S): S
}
type BarReturnType = ReturnType<Bar<string>>  // string

In other words, can we convert from type Foo to type Bar, and vice versa?

When defining a function with generics, it takes the format of type Foo. However, when passing around the return type, it is more convenient to use the format of Bar.

One approach is to separately define the return type using generics and then incorporate it into the function. However, this may lead to splitting one's code and making it messier.

Answer №1

Currently, there is no direct way at the type level to switch between generic types and generic call signatures in TypeScript. The generic type parameters have different scopes, making it challenging to express their relationship effectively within the type system. To address this issue, higher kinded types as requested in microsoft/TypeScript#1213, generic values as requested in microsoft/TypeScript#17574, or existentially quantified generics as requested in microsoft/TypeScript#14466 would be needed. However, TypeScript does not directly support any of these features as of TS5.0.


While the language offers limited options to represent this concept, all solutions involve operating at the value level. This means having a value of the relevant type and performing operations on that value to derive the desired type. Depending on the specific use case, working at the value level may suffice.

For instance, instantiation expressions allow converting a specific type representing a generic call signature (e.g. Foo) into a generic type representing a specific call signature (e.g. Bar), but you must possess a value of type Foo (or simulate having such a value):

type Foo = <S>(a: S) => S
type Bar<S> = (a: S) => S 

declare const foo: Foo;
type BarFromFoo<S> = typeof foo<S>; // instantiation expression
// type BarFromFoo<S> = (a: S) => S

Furthermore, leveraging higher order type inference from generic types enables transforming a generic type like Bar<S> back to Foo, but you must either currently possess or mimic having a value associated with Bar:

declare const bar: <S>() => Bar<S>;

This approach requires a function that manages transferring arguments and return types:

declare const funWithFunctions: <A extends any[], B extends any[], R>(
    f: (...a: A) => (...b: B) => R
) => (...ab: [...A, ...B]) => R // higher order generic function inference

By utilizing the above function, you can modify one type using another and retrieve its resulting type:

const fooFromBar = funWithFunctions(bar)
type FooFromBar = typeof fooFromBar;
// type FooFromBar = <S>(a: S) => S

Playground link to code

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 causing my Vue code to behave differently than anticipated?

There are a pair of components within the div. When both components are rendered together, clicking the button switches properly. However, when only one component is rendered, the switch behaves abnormally. Below is the code snippet: Base.vue <templa ...

Working with arrow functions in TypeScript syntax

I came across the following code snippet in TypeScript: (() => { const abc = 'blabla'; ... })(); Can someone explain what exactly this syntax means? I understand arrow functions in JS, so I get this: () => { const abc = &apos ...

The never-ending cycle of an Angular dropdown linked to a function being repeatedly invoked

I am currently working with a PrimeNg dropdown that is fetching its options through a function call. However, I have noticed that this function is being called an excessive number of times. Could this potentially impact the performance or any other aspect? ...

Utilizing StyleFunctionProps within JavaScript for Chakra UI Enhancements

I need help figuring out how to implement StyleFunctionProps in my Chakra UI theme for my NextJS project. The documentation on Chakra's website provides an example in Typescript, but I am working with Javascript. Can someone guide me on adapting this ...

The button event listener in React fails to trigger without a page refresh

Within my index.html file, I have included the following code snippet: <head> ... <script type="text/javascript" src="https://mysrc.com/something.js&collectorId=f8n0soi9" </script> <script ...

Lack of MaterialUI Table props causing issues in Storybook

Currently, I am utilizing MaterialUI with some modifications to create a personalized library. My tool of choice for documentation is Storybook, using Typescript. An issue I have encountered is that the storybook table props are not consistently auto-gene ...

Merging Type-GraphQL and Typegoose through a Variety of Decorators

Using a combination of Type-GraphQl and Typegoose, I aim to streamline my data definitions by consolidating them into one source for both GraphQL schemas and Mongoose queries. Is it feasible to merge the two libraries in a way that allows me to describe bo ...

What is the process for creating a unit test case for an Angular service page?

How can I create test cases for the service page using Jasmine? I attempted to write unit tests for the following function. service.page.ts get(): Observable<Array<modelsample>> { const endpoint = "URL" ; return ...

Exploring how NestJS can serialize bigint parameters within DTOs

I have data transfer objects (DTOs) with parameters that are of type bigint. However, when I receive these DTOs, the parameters always have a type of string. Here is an example: @Get("") async foo(@Query() query: Foo) { console.log(typeof Foo ...

Tips for toggling visibility in Angular 2

I utilized [hidden] in the following way where the value of "secondTab" is set to true. <form #siteForm="ngForm" novalidate (ngSubmit)="saveSite(siteForm.value,siteForm.valid)" class="admin-modal"> <div class="txt-danger">{{errorMessage}}&l ...

Utilize nested object models as parameters in TypeScript requests

Trying to pass request parameters using model structure in typescript. It works fine for non-nested objects, but encountering issues with nested arrays as shown below: export class exampleModel{ products: [ { name: string, ...

Unable to access structuredClone on the global object within a Node.js application

structuredClone is causing issues in my NodeJS application. Whenever I try to utilize it, I encounter the error: structuredClone is not defined nodejs. To troubleshoot, I created a simple file and executed the following: console.log({ globals: Object. ...

How do I assign a default value to an optional parameter in a derived class in Typescript?

One of my classes is called ClientBase: export class ClientBase { constructor(private uri: string, private httpClient: HttpClient) { } // Contains Various Methods } I have multiple subclasses that are derived from the ClientBase For instance: @I ...

What are the solutions for handling undefined data within the scope of Typescript?

I am encountering an issue with my ngOnInit() method. The method fills a data list at the beginning and contains two different logic branches depending on whether there is a query param present (navigating back to the page) or it's the first opening o ...

Having difficulty grasping the significance of the data received from the API response

Currently, as I am working on my personal Portfolio for a Web Developer course, I have encountered an issue with correctly implementing my API to retrieve information from the database. Previously, I faced no problem when using a .json file, but now, I am ...

I'm stuck trying to figure out all the parameters for the MapsPage component in Angular 2

Currently, I am utilizing Angular2 with Ionic2 for my mobile app development. Everything was working flawlessly until I decided to incorporate a new module for Google Maps navigation. Specifically, I am using phonegap-launch-navigator for this purpose. The ...

When modifying the state of an array within a component, certain values may be overwritten and lost in the process

Currently, I'm faced with the challenge of ensuring that a component displays a loading screen until all images have completed loading. This is necessary because there are approximately 25 images that must finish loading before the page can be display ...

Integration of Mocha with WebStorm

WebStorm offers a useful feature that adds a small arrow next to describe() and it() keywords when writing tests with Mocha, allowing for easy manual execution. However, there is a challenge: I require additional setup before each test, leading me to use ...

What is the best way to send information to a child component that has been navigated from a parent component

When navigating to a child component from the parent component's HTML template using a button, how can I pass the parent component's data (such as a name) to the child component without displaying it in the URL? ...

After performing the `ng build --prod` command in Angular 4, deep linking functionality may not

I have a requirement to display different screens in my Angular application based on the URL pasted by the user in the browser: http://localhost/screen1 (should show screen1) http://localhost/screen2 (should show screen2) To achieve this, I have set up ...