最近在使用typescript写工具库时,遇到了一个问题,就是如何优雅地使用typescript的类型定义来定义一个类,这么说有点抽象,比如我有下面这个factory函数:
function factory(expect: any): any
函数的功能很简单,即传入一个类构造函数,并返回这个类的一个实例对象,比如存在一个类:
class Product {
id: number
name: string
}
我们知道,Product表面上表示一个类,实际上这是es6的语法糖,即实际上是一个类的构造函数,所以我们可以将其传入factory函数,我期望的是,当我这样调用的时候,result会接受一个Product实例对象。
const result = factory(Product)
很明显,上面的代码虽然可以运行,但是result的类型信息却丢失了。当然,我可以像下面这样,将result强转为Product以获得类型。
const result = factory(Product) as Product
但这不是我想要的,所以,我们需要创建一种类型来表示一个构造函数,而且,这种类型是一个泛型类型。
type Constructor<T> = new (...args: any[]) => T;
上面的代码表示,Constructor是类T的一个构造方法,于是乎,我们可以重新改写我们的factory函数:
function factory<T>(expect: Constructor<T>): T
在这之后,我们就可以这样调用代码:
const result = factory(Product)
编译器会自动帮我们推断T的类型,故泛型参数可以省略,同时,result也获得了相应的类型信息。