在阅读关于装饰器的TS文档时,发现了以下语法:
function classDecorator<T extends {new(...args:any[]):{}}>(constructor:T) {
return class extends constructor {
newProperty = "new property";
hello = "override";
}
}
我不完全理解使用的以下泛型
<T extends {new(...args:any[]):{}}>
我通常理解泛型,也理解泛型中的extends
关键字。然而,我现在想了解以下语法{new(...args:any[]):{}}
的含义,特别是在泛型表达式中使用new
、扩展...
运算符和对象文字语法{}
。
{new(...args:any[]):{}}
这个结构的总体含义如下:
"具有接受任意类型的可变数量的参数的构造函数的某个对象";。
...args
是一个javascript(因此也是typescript(变量参数声明:
function f(...args: string[]) {}
f("asd", "a", "v")
在这种情况下,{}
返回类型只是字面上的空对象。
则类型脚本extend
释放了函数params的约束(因为任何函数params组合都确实扩展了...args: any[]
(对于返回类型(因为任何对象都扩展了{}
,构造函数隐式返回构造的对象(
因此该签名意味着:";给我任何可以通过new
关键字创建的东西,不管怎样">
ts操场上的小例子
它基本上是一个类检查(一个带有构造函数的对象(
{new ... }
这些左大括号和右大括号表示我们正在对象内部工作。类似:{num: number}
new(...args: any[])
这里的new
关键字强调了我们正在寻找具有构造函数的东西。...args: any[]
只是声明该类型不关心该构造函数的参数。
更具体地说,具有三点状态的...args
可以有任何数量的参数,而any[]
意味着这些参数可以具有any
类型,这意味着它们绝对可以是任何东西。
然后:
: {}
这说明构造函数应该返回一个对象,如果它是为类返回的,那么它很可能会返回。
我从来没有见过它这样写,通常情况下,只写这样就足够了:
<T extends new (...args: any[])=>Object>
原始脚本需要封装在{...}
中的原因是,使用冒号:
而不是箭头=>
会混淆类型脚本,因为它不希望在对象或类型定义之外使用冒号。
总而言之,拥有这种类型是有意义的,因为它确保了这个装饰器只能应用于一个类,并在装饰器本身中对其进行类型化。