Typescript:通过装饰器工厂上的TypedPropertyDescriptor限制装饰器

时间:2018-10-24 04:37:19

标签: node.js typescript

我知道限制装饰器可以应用的标准方法是使用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 {...}

2 个答案:

答案 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)

问题在于我们对这些方法的签名实际上是anyPromise<any>已满。

非常感谢@ TitianCernicova-Dragomir帮助弄清楚了这一点。