我们有一个类似这样定义的类
const A = class<T> {a: T}
目标是用参数string
描述此类的一种实例目前我拥有的是
const instanceType: InstanceType<typeof A>
但是我不知道如何通过类型参数
我不会问你为什么不只是"正常方式"做事。那是您的事!😀
我认为这是语言的边缘案例之一,因为缺乏通用值或其他高阶类型会咬您。当您"正常"定义类时:
class B<T> { b!: T }
TypeScript为实例创建了一个新的nate nastic type B<T>
,并为构造函数创建了一个新的命名non-generic non-Generic 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>
。
更糟糕的是,您当前无法使用条件类型检查A
的类型来插入通用参数。这是TS的设计限制。基本上,缺乏高阶类型的支持正在阻碍我们的方式。可能有一些可能解决此问题的更改,但它们尚未使用该语言。
如果我们不能纯粹在类型级别上执行此操作,我们可以通过运行时效应来做到:
const instanceOfAString = new A<string>();
type InstanceOfAString = typeof instanceOfAString;
如果您不想真正致电构造函数只是为了取出类型,则可以使用控制流程来防止它:
if (false) {
// never called
var instanceOfAString = new A<string>();
}
type InstanceOfAString = typeof instanceOfAString;
在运行时从未真正调用构造函数,但是类型系统仍然确定您可以抓取的instanceOfAString
类型。是的,从运行时起,它并不是完全看不见的……它出现在发射的JavaScript中,即使它本质上什么也不做。这是一个解决方法。
有一个旧的建议可以让您执行诸如type InstanceOfAString = typeof (new A<string>())
之类的事情,而无需在运行时调用任何内容,但这也不支持。所以这是我最接近的。🤷
另一种方法是自己创建类型A
,以某些代码重复为代价:
const A = class <T> { a!: T };
type A<T> = { a: T };
现在您可以"按正常"使用它:
type InstanceOfAString = A<string>;
当然,如果A
具有很多属性,您本质上将两次列出它们。
无论如何,希望其中一个想法会有所帮助。祝你好运!