我知道限制装饰器可以应用的标准方法是使用TypedPropertyDescriptor,例如export function decorator(target, key, TypedPropertyDescriptor<T extends ...>) {...}
按原样使用时效果很好。但是,如果涉及装饰器工厂,则TS编译器似乎不再强制执行它。
即:export function whatever (param: SomeThing) { return function decorator(target, key, TypedPropertyDescriptor<T extends ...>) {...} }
您可以将(^)放在任何您喜欢的东西上,这将达到目的。通过工厂使用时如何限制装饰器?
我尝试四处搜寻,但找不到任何东西。
完整示例:
export function AsyncEndpoint(
method: string,
path: string,
model?: ClassType<IRequest>,
validationRules: any = {},
responseStatus: number = HttpStatus.OK,
base: string = "v1"
) {
// noinspection TsLint
return function(
target: Controller, // This is the class prototype
propertyKey: string, // This is the prop/method name called
descriptor: TypedPropertyDescriptor<(...p: any[]) => Promise<any>>
): any {...}
答案 0 :(得分:1)
该问题是由于以下事实引起的:该函数重新调整了any且装饰器将与any
兼容,因为any
与任何约束都兼容。
您可以避免装饰器与使用this技巧来检测any
的函数返回的函数兼容:
class SomeThing { }
type IfAny<T, Y, N> = 0 extends (1 & T) ? Y : N;
function whatever(param: SomeThing) {
return function decorator<T extends () => Promise<any>>(target: Object,
propertyKey: string | symbol,
descriptor: TypedPropertyDescriptor<T> & IfAny<ReturnType<T>, "Any not allowed retrun a promise", {}>) {
}
}
class test {
@whatever(new SomeThing()) /*err*/
m() : any{
}
@whatever(new SomeThing()) /*ok*/ mw() {
return Promise.resolve("")
}
}
答案 1 :(得分:0)
问题在于我们对这些方法的签名实际上是any
,Promise<any>
已满。
非常感谢@ TitianCernicova-Dragomir帮助弄清楚了这一点。