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



我们有一个类似这样定义的类
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具有很多属性,您本质上将两次列出它们。


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

相关内容

最新更新