将通用类型参数传递给类表达式

时间:2019-03-07 14:48:15

标签: typescript

我们有一个这样定义的类
const A = class<T> {a: T}

目标是使用参数string描述此类的实例的类型

目前我拥有的是
const instanceType: InstanceType<typeof A>

但是我不知道如何传递类型参数

1 个答案:

答案 0 :(得分:1)

我不会问你为什么不只是以“正常方式”做事。那是您的事!


我认为这是缺少generic values或其他higher order types的语言所困扰的其中一种。当您“正常”定义类时:

class B<T> { b!: T }

TypeScript为实例创建一个新的命名通用 type B<T>,并为构造函数创建一个新的命名为非通用 value B, (其类型为通用构造函数),如下所示:

type B<T> = {b: T};
declare const B: new<T>()=>B<T>;

因此,在这种情况下,如果要引用将T设置为string实例化的实例类型,就可以了:

type InstanceOfBString = B<string>; // okay

但是您执行此操作的方式将创建命名的 value ,但不会创建命名的类型:

const A = class <T> { a!: T };

因此,现在您没有名为A的类型可以使用:

type InstanceOfAString = A<string>; // error, cannot find name A

由于值A不是通用的(因为没有通用值),所以您也不能写(typeof A)<T>

更糟糕的是,您目前无法使用conditional types来检查A的类型以插入通用参数。从3.3开始,这是TS的design limitation。从根本上说,缺少高阶类型支持已成为我们的障碍。有些possible changes可能会解决此问题,但尚未使用该语言。

如果我们不能仅在类型级别上做到这一点,就可以通过运行时效果来做到这一点:

const instanceOfAString = new A<string>(); 
type InstanceOfAString = typeof instanceOfAString;

如果您不想仅仅为了获取类型而实际调用构造函数,则可以尝试使用控制流来阻止它:

if (false) {
  // never called
  var instanceOfAString = new A<string>(); 
}
type InstanceOfAString = typeof instanceOfAString;

构造函数永远不会在运行时真正调用,但是类型系统仍会为instanceOfAString确定一个您可以抓住的类型。是的,它在运行时并不是完全不可见的……它出现在发出的JavaScript中,即使它实际上什么也不做。这是一种解决方法。

an old proposal可以让您执行类似type InstanceOfAString = typeof (new A<string>())的操作,而无需在运行时调用任何东西,但这也不被支持。所以这是我能得到的最接近的。


另一种可行的方法是自己创建类型A,但要花一些代码重复:

const A = class <T> { a!: T };
type A<T> = { a: T };

现在您可以“正常”使用它:

type InstanceOfAString = A<string>;

但是,当然,如果A具有很多属性,则实际上您将它们列出两次。


无论如何,希望其中一个想法能有所帮助。祝你好运!

相关问题