【问题标题】:Typescript signature for higher-order decorator function高阶装饰器功能的打字稿签名
【发布时间】:2018-10-12 15:11:58
【问题描述】:

是否可以为装饰器函数编写类型签名(我的意思是装饰器设计模式装饰器,而不是打字稿装饰器功能)?

我试过了:

function decorate<T extends () => any>(callback: T): T {
    return (...args) => {
        console.log('called with args: ', args);
        return callback(...args);
    };
}

但它给了我TS2322: Type '(...args: any[]) =&gt; any' is not assignable to type 'T'.

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您可以在 3.0 中使用 Tuples in rest parameters and spread expressions 执行此操作

    function decorate<A extends any[], R>(callback: (...a: A) => R): (...a: A) => R {
        return (...args) => {
            console.log('called with args: ', args);
            return callback(...args);
        };
    }
    
    function foo(s: number) {
        return s.toString();
    }
    
    
    function bar(s: number, o : string[]) {
        return s.toString();
    }
    
    var dBar = decorate(bar) // (s: number, o: string[]) => string
    var dFoo = decorate(foo) // (s: number) => string
    

    正如 cmets 中所指出的,有一些注意事项。泛型不适用于这种方法。上面的函数也不能正确处理重载。有关过载问题的解决方法,请参阅this answer

    编辑

    一个使用较少警告但在实现中需要一些类型断言的版本与您建议的版本接近:

    function decorate<T extends (...a: any[]) => any>(callback: T): T {
        return ((...args) => {
            console.log('called with args: ', args);
            return callback(...args);
        }) as any;
    }
    

    这更好地捕捉到输入与输出相同,并且如果不需要对返回类型或参数进行其他类型操作,则更可取。虽然这个版本破坏了实现类型安全,但这是一个可以接受的折衷以获得完整的调用站点安全,因为它可以与重载和泛型一起使用。

    【讨论】:

    • 除非原始函数是通用的。 :(
    • @MattMcCutchen 是的,或者有过载..有一些警告是真的。
    • @amik 添加了一个警告较少的替代版本
    猜你喜欢
    • 1970-01-01
    • 2018-05-10
    • 2020-03-28
    • 2018-11-07
    • 2016-09-27
    • 2018-06-16
    • 2018-06-21
    • 2019-07-29
    • 2016-05-08
    相关资源
    最近更新 更多