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

Ionic 2: Unveiling the Flipclock Component

Can anyone provide guidance on integrating the Flipclock 24-hours feature into my Ionic 2 application? I'm unsure about the compatibility of the JavaScript library with Ionic 2 in typescript. I have searched for information on using Flipclock in Ionic ...

Utilizing various filters and sorting options on API response within Angular 8

Upon receiving the following API response: [ { "imgPaths":[ "gallery/products/55ccb60cddb4d9bded02accb26827ce4" ], "_id":"5f3e961d65c6d591ba04f3d3", "productName":" ...

What is the method to insert a new <input> element after the last input field has been filled in

I recently started working on a form using StackBlitz, but I've hit a roadblock and need some guidance on how to proceed. My goal is to achieve a similar effect like the one shown in this gif: https://i.stack.imgur.com/76nsY.gif and I'd like to ...

What is the method for accessing an anonymous function within a JavaScript Object?

Currently facing an issue with a Node.js package called Telegraf, which is a bot framework. The problem arises when trying to create typings for it in TypeScript. The package exports the following: module.exports = Object.assign(Telegraf, { Composer, ...

Context failing to refresh value upon route changes

My current context setup is as follows: import { createContext, ReactNode, useState } from "react"; type props = { children: ReactNode; }; type GlobalContextType = { name: string; setName: (value: string) => void; }; export const Glob ...

Choosing to overload the plainToClass function may result in a type error

I've been tasked with compiling an angular project that contains mostly code written by someone else. Although the example below compiles successfully on one machine, it throws an error on different machines. import { plainToClass } from 'class ...

Obtain PDF File using Typescript

I am attempting to use an AJAX Post to download a PDF file and return the templateFile Model. However, I am encountering an error where it cannot convert type TemplateFileDto to IhttpActionResult. Should I consider returning something different? Any assist ...

How can TypeScript be used to enable CSV or PDF export in a material-react-table?

Is it possible to incorporate the ability to export data to CSV or PDF in a material-react-table? While I am familiar with how to do this with a Material UI table, I have not been able to find the same functionality for the material-react-table. Thank you ...

Do you have an index.d.ts file available for canonical-json?

I am currently working on creating an index.d.ts file specifically for canonical-json. Below is my attempted code: declare module 'canonical-json' { export function stringify(s: any): string; } I have also experimented with the following sn ...

Encountering an issue with a MEAN application using Angular 2: The error message states "Cannot read property

As a first-time application developer, I am working on creating a system to manage Client profiles. Utilizing the Angular tour of heroes for the basic structure, I integrated mongodb and express components sourced from various online platforms. However, I ...

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 ...

I have a question about TypeScript mapped types. Why is it not possible to retrieve the keys of a union of interfaces?

Below is the code snippet that I am working with: interface Data { A: { a1: string; a2: string; }; B: { b1: number; b2: string; }; } type TransformDataKey<V extends string, T extends string> = `--${V}-${T}`; type TransformDa ...

Is there a way to incorporate margins into a React component using TypeScript?

I am currently facing a challenge in passing CSS attributes to a component that I am working with. The reason behind this is that I need to modify the margins to fit a specific space, hence my attempt to directly pass the margins. Does anyone have any sug ...

Bind the change event of an Angular input to a variable that contains a custom function

Is there a way to achieve something similar to the following? <input (input)="doSomething($event)" /> <input (input)="boolVar = $event.target.value > 5" /> I would like to accomplish it by defining a function, like this: funcVar = (e) =&g ...

The expanded interfaces of Typescript's indexable types (TS2322)

Currently, I am in the process of learning typescript by reimagining a flowtype prototype that I previously worked on. However, I have hit a roadblock with a particular issue. error TS2322: Type '(state: State, action: NumberAppendAction) => State ...

Instead of the type definition file, navigate to the TypeScript source file within VS Code

A unique npm library I developed is utilized in various main projects, with all the sources stored within a /src directory and written in TypeScript. The compiler options listed in the tsconfig.json file include "sourceMap": true and "outDir": "dist". Addi ...

What could be causing the availability of a response in a service, but showing as undefined in the component?

Currently, I am facing a problem with my service and component setup. While the service can successfully read the response as a JSON object, the component is returning res: undefined. service: constructor( private http: Http, private fbuilder: Fo ...

Passing a click event to a reusable component in Angular 2 for enhanced functionality

I am currently working on abstracting out a table that is used by several components. While most of my dynamic table population needs have been met, I am facing a challenge with making the rows clickable in one instance of the table. Previously, I simply ...

Transferring data from a child component to a parent component in Vue without the need for a click

In my Vue project, I have a parent component called ChangeInfo which contains a child component named ShowWorkInfo. The ShowWorkInfo component includes several input forms for updating job information. To manage the data input, I created an object variable ...

Encountered issues while trying to utilize wasm function within Vue framework

When attempting to integrate wasm with Vue, I encountered a frustrating issue where the startQuorum function in my wasm file could not be located. import { Go } from './wasm_exec' import quorumWasmUrl from './lib.wasm' export const sta ...