0

We have GetInnerType type which return the generic type parameter for every type extending Foo class:

class Foo<T> {}

type GetInnerType<X> = X extends Foo<infer I> ? I : never;

Can we abstract GetInnerType so that it works with any generic class?

The new version of GetInnerType should behave like below:

class Bar<T>{}

let v1 = new Foo<number>();
let v2 = new Bar<{a: string}>();
type t1 = GetInnerType<typeof v1>; // is number
type t2 = GetInnerType<typeof v2>; // is {a: string}
serrulien
  • 695
  • 4
  • 14

1 Answers1

0

This is impossible because the result is not well-defined. Consider the example below:

class A<T> {
    constructor(public a: T, public b: number) {}
}

class B<T> {
    constructor(public a: string, public b: T) {}
}

// true
type AextendsB = A<string> extends B<number> ? true : false

// true
type BextendsA = B<number> extends A<string> ? true : false

Playground Link

Typescript's type system is structural, not nominal, so if two types have the same structure then they are the same type, even if they were declared with different names. In the above example, the type A<string> is equal to the type B<number>, and both are equal to {a: string, b: number}.

It follows that however you define GetInnerType, the result of GetInnerType<A<string>> is necessarily the same as the result of GetInnerType<B<number>>, so you can't get string in the first case and also get number in the second case.

kaya3
  • 47,440
  • 4
  • 68
  • 97