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