Skip to content

Defining a type with inferred generic parameters #64938

Open

Description

🔍 Search Terms

infer type generic parameters

Related comment:

Did find some issue about "Higher-kinded types", but none on inference.
Do not confuse this issue with the ones asking for an infer in the generic type contraints.

✅ Viability Checklist

⭐ Suggestion

Allowing an infer keyword when defining a generic type:

type Y<T extends number> = {};
type X<infer T> = Y<T>;
// equivalent to:
type X<T extends number> = Y<T>

The infer keyword would tell TS that the contraints (and default value) of T should be fetched from the definition of Y.

Possible improvement:

When we have multiple generic parameters, it could also be nice to be able to do:

type X<infer ..T> = Y<..T>

But IIRC some issues already request features for a ..T.

Possible alternative 1:

Being able to fetch a generic parameter definition from an existing type:

type Y<T extends number> = {};

type X<T extends Y{T}> = Y<T>;
type X<T extends Y{1}> = Y<T>; // starts at 1 if we want 0 to have a special meaning.
type X<T: Y{1}> = Y<T>;

Possible alternative 2:

Being able to define generic parameters outside of type definition:

typeparams P = [
      T extends number,
      U extends string,
];

type Y<..P> = { foo: P.T, faa: P.U };
type X<..P> = Y<..P>;

For this one, a current alternative is to use a bag:

type P = {
      T: number,
      U: string
}

type Y<T extends P> = {foo: T["T"], faa: T["U"]};
type X<T extends P> = Y<T>;

However, I'm pretty sure it causes issues when inferring.

📃 Motivating Example

When defining generic types from other generic types, we have to copy/paste all the contraints.
This code duplication is a pain, makes the code harder to read, and can be error prône if the contraints change.

type Y<
                 T extends A<number>,
                 U extends B<any>,
                 V extends C<any>
> = {};

type X<infer T, infer U, infer V> = Y<T, U, V>;
// vs
type X<
                 T extends A<number>,
                 U extends B<any>,
                 V extends C<any>
            > = Y<T, U, V>;

💻 Use Cases

  1. What do you want to use this for?

Easily defining generic types from other generic types.

  1. What shortcomings exist with current approaches?

Lot of duplicated contraints.

  1. What workarounds are you using in the meantime?

Duplicated contraints.

Activity

  1. MartinJohns commented on Oct 23, 2026

    @MartinJohns
    Contributor

    Duplicate of #29469.

  2. denis-migdal commented on Oct 24, 2026

    @denis-migdal
    Author

    The underlying issue is indeed the same, however, the feature requests differ.
    I think my proposal would be better.

    Initially, they ask for type X<T> = Y<T> to automatically get the constraint from Y, which may break existing code base : type X<T> = T extends Z ? Y<T> : never how should it behave ?

    A second comment asks for type X<T> = Y<infer T>, however this would require "flowing the constraints backwards from usages". How should it behave when doing type manipulation on T ? Or when doing: type X<T> = Y<infer T> & Z<infer T> ?

    In my proposal, we know from the start that T is special. We can simply forbid type manipulations on/with it.
    I guess we could authorize type X<infer T> = Y<T> & Z<T>, by making T <T extends Y1 & Z1>.

    The alternative solution 1:

    This entirely solves the issue of inference as we explicitly provide the constraint and default value:

    type Y<T extends number> = {};
    type X<T extends Y{1}> = Y<T>;
    type X<T: Y{1}> = Y<T>; // also fetch the default.

    We could also make it stronger:

    type Y<T extends number, U extends string, V extends string = "ok"> = {};
    type X<..P: Y{1,2,3}> = Y<P{1}, P{2}, P{3}>;
    type X<..P: Y{1,2,3}> = Y<..P>;
    type X<..P: Y{1:3}> = Y<..P>;
    type X<..P: Y{*}> = Y<..P>;

    Note: this also enable to declare parameters

    type Params<T extends string, U extends number> = {};
    
    type Y<..P: Params{*}> = ...;
    type X<..P: Params{*}> = Y<..P>;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions