Search code examples
typescriptgenericstypescript-generics

Why does typescript not allow to partially specify type arguments in order to create a new generic function from another generic function?


I'm learning about generic in typescript, specifically Instantiation Expressions.

I wonder that: Why typescript does not allow to partially specify type arguments in generic function in order to create a new generic function which has less type variables (the new generic function is less flexible and reusable in terms of type than the old one).

For example:

type TypeA = { a: string };         // line (1)

function mergeFunc<T_1, T_2>(a: T_1, b: T_2) {      // line (2)
    return { ...a, ...b };                          // line (3)
}

let newGenMergeFunc = mergeFunc<TypeA, Tp>;         // line (4)

In the example, I have one type definetion (typeA) and mergeFunc function which contain 2 type variables (T_1 and T_2). Type signature of mergeFunc is: mergeFunc<T_1, T_2>(a: T_1, b: T_2): T_1 & T_2

I want to create a more specific version of mergeFunc using instantiation expression. I have created a new function (newGenMergeFunc) by passing actual type TypeA to the first type parameter (T_1) and keeping the second type parameter being as a type variable (Tp).

When I run the example above, I expect that: newGenMergeFunc will become a generic function having one type variable (Tp) and its signature is :

newGenMergeFunc<Tp>(a: TypeA, b: Tp): TypeA & T_2. In that, TypeA is the actual type while Tp is a type parameter ( type placeholder or type variable). However, Typescript compiler does not permit me to do that.

Could you give the reason? Thanks for considering my stupid question.


Solution

  • You can, but the syntax you used is incorrect.

    let newGenMergeFunc:<Tp> (a: TypeA, b: Tp) => TypeA & Tp = mergeFunc;
    

    You need to have a context where Tp is already a type parameter for mergeFunc<TypeA, Tp> to be valid, e.g.

    function makeMergeFunc<Tp>(){ return mergeFunc<TypeA, Tp>; }
    let unknownMergeFunc = makeMergeFunc();
    

    Playground link