I need to implement a type GetClassParameter<T> that would work like this:
class Foo<T> {
}
type foo = Foo<string>
type x = GetClassParameter<foo>; // should be string
I'm sorry if it's a duplicate, I couldn't find it. I only found a hardcoded solution (source):
type GetFooParameter<T extends Foo<any>> = T extends Foo<infer R> ? R : unknown;
I tried to do something like this:
class Foo<T> {
public value: T;
public value2: string;
constructor (value: T) {
this.value = value;
}
}
type BaseT<T> = {
value: T // if removed, it wouldn't work
}
type GetClassParameter<T extends BaseT<any>> = T extends BaseT<infer R> ? R : unknown;
type x = GetClassParameter<foo> // string - almost works, requires shared property with a T
The above almost works but requires BaseT to have a value: T property.
Is there a way to do it without hardcoding anything, assuming the target class has only one generic parameter?
Update:
Another take, unsuccessful.
type ClassLike<T> = (new <T>(...args: any[]) => any);
type GetClassParameter<T extends ClassLike<any>> = T extends ClassLike<infer R> ? R : unknown;
type x = GetClassParameter<foo> // error, does not satisfy constraint
Update 2
It's not possible currently. Nevertheless, I tried a hack to define BaseT with value property and then removed it. It doesn't work. I'm adding it as a reference if someone had a similar idea to save you time. playground
Update 3
I'm adding a workaround I'm using to get the class parameter type for 2 classes that have nothing in common (it can be extended to cover more classes just by adding additional conditional).
class Alpha<T> {
private a: T;
}
class Beta<T> {
private b: T;
}
type GetClassParameterForAlphaBeta<T extends Alpha<any> | Beta<any>> =
T extends Alpha<infer R>
? R : T extends Beta<infer R>
? R : unknown;
type alpha = Alpha<string>
type beta = Beta<number>
type x = GetClassParameterForAlphaBeta<alpha> // string
type y = GetClassParameterForAlphaBeta<beta> // number
GetClassParameter<typeof Foo>, if that also works for youGetClassParameter<typeof foo>doesn't seem to work.UtilType<F<T>> => Tis not supported by TS. Higher kinded type is the term, and TS doesn’t have it. So forget perfect solution, best you can get is workarounds with limitations. Your two takes are actually good enough.