Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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"`
like image 432
Gerrit Begher Avatar asked Mar 27 '20 19:03

Gerrit Begher


People also ask

How do you find the type of generic type?

Use the IsGenericType property to determine whether the type is generic, and use the IsGenericTypeDefinition property to determine whether the type is a generic type definition. Get an array that contains the generic type arguments, using the GetGenericArguments method.

How do you pass a generic type as parameter TypeScript?

Assigning Generic Parameters By passing in the type with the <number> code, you are explicitly letting TypeScript know that you want the generic type parameter T of the identity function to be of type number . This will enforce the number type as the argument and the return value.

How do you get typeof a variable in TypeScript?

Use the typeof operator to check the type of a variable in TypeScript, e.g. if (typeof myVar === 'string') {} . The typeof operator returns a string that indicates the type of the value and can be used as a type guard in TypeScript.

What is generic type in TypeScript?

TypeScript Generics is a tool which provides a way to create reusable components. It creates a component that can work with a variety of data types rather than a single data type. It allows users to consume these components and use their own types.


1 Answers

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

like image 132
Tim Avatar answered Oct 01 '22 05:10

Tim