如何编写一个正确处理静态方法的类型安全类装饰器?
具体来说,这个装饰器适用于没有静态方法的类:
interface ITypeOf<T> {
new(...args: any[]): T
}
function decorate<T>(cls: ITypeOf<T>): ITypeOf<T> {
return cls
}
但是ITypeOf
并不考虑静态属性,因此当它应用于具有静态属性的类时,编译失败并显示此错误:
@decorate
class Foo {
static bar() {
return 42
}
}
产生错误:
Unable to resolve signature of class decorator when called as an expression.
Type 'ITypeOf<Foo>' is not assignable to type 'typeof Foo'.
Property 'bar' is missing in type 'ITypeOf<Foo>'.
function decorate<T>(cls: ITypeOf<T>): ITypeOf<T>
以下是一个工作示例: http://www.typescriptlang.org/play/#src=interface…
如何编写适用于具有静态成员的类的类型安全类装饰器?
答案 0 :(得分:5)
装饰器的返回类型必须与它正在装饰的类类型兼容,因为装饰器的返回值将在运行时替换类。要实现这一点,我们必须使用表示类本身的泛型参数,它既是参数的类型,也是返回类型。因此,我们将返回一个与输入类(包括静态)具有相同结构的类,并且编译器将得到满足:
function decorate<TCtor extends ITypeOf<any>>(cls: TCtor): TCtor {
return cls
}
@decorate
class Foo {
static bar() {
return 42
}
}
要对要装饰的类添加限制,我们可以更加限制ITypeOf
的类型参数:
// decorated class must have a field x: numeber
function decorate<TCtor extends ITypeOf<{ x: number }>>(cls: TCtor): TCtor {
return cls
}
@decorate // error no instance x
class Foo { }
@decorate // ok
class Boo { x!: number }
我们还可以添加有关静态成员的限制
// decorated class must have a static field x: numeber
function decorate<TCtor extends ITypeOf<any> & { x: number }>(cls: TCtor): TCtor {
return cls
}
@decorate // error no static x
class Foo { }
@decorate // ok
class Boo { static x: number }
答案 1 :(得分:0)
如何编写适用于类的类型安全类装饰器 与静态成员?
这取决于你在装饰者里面要做什么。
你可以简单地让decorator
像这样完全通用:
function decorate<C>(cls: C) {
return cls;
}
但是,这不会捕获有关C
的任何信息,因此您无法对cls
内的decorate
做多少工作。
或者你可以有单独的通用参数,一个用于&#34;实例端&#34; cls
和另一个用于&#34;静态&#34;:
interface ITypeOf<T> {
new(...args: any[]): T
}
function decorate<I, S extends ITypeOf<I>>(cls: S): S {
return cls
}
@decorate
class Foo {
static bar() {
return 42
}
}