8

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"`
8
  • 1
    What exactly is the behavior you're looking for here? It would help if you can give a more detailed example, are you just looking to get the return type of the generic function passed in? Commented Mar 30, 2020 at 7:46
  • I added some examples Commented Mar 30, 2020 at 7:59
  • Unable to figure out what you are trying to achieve. Suggest you provide some use case for your requirement. Commented Mar 30, 2020 at 8:06
  • 1
    I have a feeling you would need to be able to use higher kinded types to do this since at some point your Arr type (which is a generic within the Ev type) would need to be parameterized by another generic which -as far as I'm aware- isn't possible in Typescript. Commented Mar 31, 2020 at 0:44
  • 2
    Agree with @Xetera, it would indeed require parametrization of a parametrized. See here: github.com/Microsoft/TypeScript/issues/1213 Commented Mar 31, 2020 at 10:59

2 Answers 2

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

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your expository answer. So the answer seems to be "not possible in TS". However, while there is no native support for HKTs in TS, it is still very much possible to implement (some features of) HKTs. See for example (github.com/gcanti/fp-ts). One feature that I did not manage to implement however, are lambda expressions at the type level. The question aims at this: If we could replace ??? with an expression that has the desired properties, some form of lambda at the type level can be achieved. Since HKTs can be hacked together, my hope was that ??? is possible as well.
0

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.

1 Comment

You seem to have misread/misunderstood the question. EV would need two type parameters.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.