'Typescript: Evaluate type of generic function
Is there any trick to "evaluate" the type of a generic fuction?
Consider the following:
type Arr = <A>() => A[]
type Ev<G, A> = ???
Question: Is it possible to fill in ???
such that Ev<Arr, A>
equals () => A[]
? (As compared to <A>() => A[]
)
(Update 2022/04/26)
Something similar/related will be possible with TS 4.7; Even though that's not fully what we'd want here.
https://github.com/microsoft/TypeScript/pull/47607
Some more examples for the desired behavior:
Ev<<A>() => A[], number>
// should evaluate to
// () => number[]
Ev<<A>() => string, number>
// should evaluate to
// () => string
Ev<<A>() => [string, A], { some: "thing" }>
// should evaluate to
// () => [string, { some: "thing" }]
A simplified version of the question would be: Can we define
type EvNum<A> = ???
such that
EvNum<
<X>() => X
> // should be `number`
EvNum<
<X>() => X[]
> // should be `number[]`
EvNum<
<X>() => [X, "hi"]
> // should be `[number, "hi"]`
EvNum<
<X>() => SomeGenericType<X>
> // should be `SomeGenericType<number>`
EvNum<
<X>() => "constant"
> // should be `"constant"`
Solution 1:[1]
As to your first question, those are referred to as Higher Kinded Types, and are not supported in Typescript as of this answer.
A Higher Kinded Type is simply "A type that abstracts over some type that, in turn, abstracts over another type." So if you want a type, that you pass in a type to abstractly create a new type, that is an example of a higher kinded type. And it is not possible in TS.
You cannot pass a second type into a generic type and come out with a derived type.
Your last example (simplified) is literally ReturnType so not sure what you are meaning. It is perfectly possible to come up with. But you can't make a type that comes up with it.
type EvNum<T> = () => T;
type Arr<T> = T[];
function func<T>(param: EvNum<T>): T {
return param();
}
let x1 = func(()=> 4); //number
let x2 = func(()=> [4]); //number[]
let x3 = func(()=> [4, "hi"] as const); //[4, "hi"]
let x4 = func(()=> "constant" as const); //"constant"
let cool: Arr<number> = [4, 5, 6];
let x5 = func(() => cool); //Arr<number>
This passes your requested types
Solution 2:[2]
If I understand you correctly it should be:
type EV<T> = () => T;
Otherwise the question makes no sense or must be explained in more detail.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Tim |
Solution 2 | Jan Bürling |