"Pass" generic type to another generic type

116 Views Asked by At

Anything new since : Is it possible to pass generic type as generic parameter? ?

My specific problem :

This work fine

type isArrStr<T extends readonly string[] > = T extends readonly["str"] ? true :false ; //dummy 
type _retAny<T> = any 

//***************
type wrapper<T>  = any extends _retAny<isArrStr<infer I>>  ? T extends I ? isArrStr<T> : never :never
//********
let myVar:wrapper<readonly["str"]> //ok , return true 
let myVar_1:wrapper<readonly["ll"]> //ok , return false
let myVar_2:wrapper<string> // ok , return never

But this doesn't

type wrapper<F,T>  = any extends _retAny<F<infer I>>  ? T extends I ? F<T> : never :never //error : Type 'F' is not generic 
//********
let myVar:wrapper<isArrStr,readonly["str"]> //error : Generic type 'isArrStr' requires 1 type argument
//let myVar_1:wrapper<readonly["ll"]>
//let myVar_2:wrapper<isArrStr,string>

Do you know something to overcome this difficulty ? Thanks for your help have nice day

I'm trying to reproduce HighOrderFunction behavior with type

2

There are 2 best solutions below

3
0xts On BEST ANSWER

No, it's still not possible to pass a generic to a generic type parameter plainly, however, it's allowed to pass one if it's constrained. I think, this approach might work for you -


type isArrStr<T> = T extends readonly ["str"] ? true : false; //dummy 
type _retAny<T> = any;

type Args<M extends Fn> = M["args"];

type Fn<Args = unknown, Return = unknown> = {
    args: Args;
    return: Return;
}

type Apply<F extends Fn, U extends Args<F>> = (F & { args: U })["return"];

interface IsArrayOfStr extends Fn {
    return: isArrStr<Args<this>>
}

type Result = Apply<IsArrayOfStr, readonly ["str"]>; // true
type Result1 = Apply<IsArrayOfStr, readonly ["11"]>; // false
type Result3 = Apply<IsArrayOfStr, string>; // false

Note that an interface is used to declare the function because the extension of types is limited and instead, an intersection is done for types. Here's a link to the playground.

4
Valeriia On

Use a helper type to pass generic type correctly:

type isArrStr<T extends readonly string[]> = T extends readonly ["str"] ? true : false;
    type _retAny<T> = any;
    type ExtractGenericParam<F> = F extends (arg: infer U) => any ? U : never;

type wrapper<F, T> = any extends _retAny<F<infer I>> ? T extends I ? F<T> : never : never;
let var: wrapper<isArrStr, readonly ["str"]>; // Returns true
let var_1: wrapper<isArrStr, readonly ["ll"]>; // Returns false
let var_2: wrapper<isArrStr, string>; // Returns never

Please let me know if you have any concerns