【发布时间】:2021-07-10 19:44:47
【问题描述】:
我需要实现一个类型GetClassParameter<T>,它可以像这样工作:
class Foo<T> {
}
type foo = Foo<string>
type x = GetClassParameter<foo>; // should be string
对不起,如果它是重复的,我找不到它。我只找到了一个硬编码的解决方案(source):
type GetFooParameter<T extends Foo<any>> = T extends Foo<infer R> ? R : unknown;
我试图做这样的事情:
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
上述方法几乎可以工作,但要求 BaseT 具有 value: T 属性。
假设目标类只有一个通用参数,有没有办法在不硬编码的情况下做到这一点?
更新:
再拍一次,不成功。
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
更新 2
目前不可能。尽管如此,我还是尝试了用 value 属性定义 BaseT 的技巧,然后将其删除。它不起作用。如果有人有类似的想法以节省您的时间,我将其添加为参考。 playground
更新 3
我正在添加一个解决方法,用于获取 2 个没有共同点的类的类参数类型(只需添加额外的条件,它就可以扩展到涵盖更多类)。
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
【问题讨论】:
-
我也尝试在类中使用这样的类型:
type ClassRef<T> = (new (...args: any[]) => any);,但我不知道在右侧插入T的位置。 -
并且TS不支持采用
UtilType<F<T>> => T的一般形式的功能。 Higher kinded type 是术语,TS 没有。所以忘记完美的解决方案,你能得到的最好的解决方法是有限制的。您的两次拍摄实际上已经足够了。 -
我再也找不到问题了,但是如果没有使用泛型,打字稿会省略它们的信息。这是一个设计限制。
-
我没有更好的答案来解决你的问题,你已经达到了 TS 的极限。仅供参考,我在几年前写了一个关于 higher kinded type in TS 的答案。仅与您的问题远程相关。如果你想深入挖掘,可以看看。
-
感谢@hackape
标签: javascript typescript typescript-typings typescript-generics