【问题标题】:Type signature for a TypeScript HOFTypeScript HOF 的类型签名
【发布时间】:2014-02-06 22:41:03
【问题描述】:

以下 JavaScript 函数为给定函数添加了前后通知。我正在尝试为此函数添加 TypeScript 类型签名。

function wrap(fn, before, after) {
    var id = function(x) { return x };
    before = before || id;
    after = after || id;

    return function() {
        var args = Array.prototype.slice.call(arguments);
        var modifiedArgs;

        try {
            modifiedArgs = before.apply(this, args);
        } catch (e) {
            console.log(e);
        }

        var result = undefined;
        try {
            result = fn.apply(this, modifiedArgs || args);
        } finally {
            try {
                after.apply(this, args);
            } catch (e) {
                console.log(e);
            }
        }

        return result;
    }
}

我能想到的类型是:

  • fnFunction 类型
  • after(_:any[]) => any[] 类型
  • 返回类型为Function

before 的类型应该是什么?它接受any[] 并返回voidany[]。此外,是否可以对返回类型与fn 具有相同类型签名的事实进行编码?

【问题讨论】:

  • 我认为更改before 建议的语义以返回null 或修改后的参数数组是这里的方法。不过我还没试过。

标签: javascript typescript


【解决方案1】:

之前可能是(_:any[]) => any[]

如果您想在函数签名中编码返回类型,只需执行以下操作:

function wrap(fn, before, after) : Function {  ...function... }

【讨论】:

  • (_:any[]) => any[]? 不会编译。我希望返回类型是与fn 相同类型的函数,即如果fn(_:string)=>string,那么返回类型是(_:string)=>string;如果fn(_:string, _:number)=>string 那么返回类型是(_:string, _:number)=>string 等等。我承认这需要一个非常有表现力的类型系统,所以在TS 中可能是不可能的,但我很好奇。
  • 我对非编译表示歉意!在这种情况下,您只是不返回函数还是返回null?我建议您返回 null 因为您可以将消息 sig 设为: (_:any[]) : any[] 并使其有效
  • 至于 fn,这超出了我的范围。我认为目前在 TS 中是不可能的。
【解决方案2】:

我最终写成这样:

module Foo {
    export interface Wrappable extends Function {
        (...rest) : any;
    }

    export function wrap<U extends Wrappable>(fn: U, 
                                              before: (...args) => any[], 
                                              after: (...args) => void): U {
        var id = function(x) { return x };
        before = before || id;
        after = after || id;

        return <U> function() {
            var args = Array.prototype.slice.call(arguments);
            var modifiedArgs;

            try {
                modifiedArgs = before.apply(this, args);
            } catch (e) {
                console.log(e);
            }

            var result = undefined;
            try {
                result = fn.apply(this, modifiedArgs || args);
            } finally {
                try {
                    after.apply(this, args);
                } catch (e) {
                    console.log(e);
                }
            }

            return result;
        }
    }
}

var orig = function(s: string): void {
    console.log("Hello!");
};

var before = function (s: string): any[] {
    console.log("before calling orig(" + s + ")");
    return [s];
};

var after = function (s: string): void {
    console.log("after calling orig(" + s + ")");
};

var f = Foo.wrap(orig, before, after);
f("1");
// f(); // ERROR
// f(1); // ERROR
// f("1", "1"); // ERROR

请注意,Foo.wrap 的返回值是与第一个参数相同类型的函数,TS 类型推断令人印象深刻!

【讨论】:

    猜你喜欢
    • 2018-01-21
    • 2019-02-21
    • 2023-03-13
    • 2013-08-03
    • 2017-02-28
    • 2020-02-02
    • 2018-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多