簡體   English   中英

如何在TypeScript中創建通用的高階函數

[英]How to create a generic higher order function in TypeScript

我不確定如何創建通常將行為添加到另一個函數的函數。 這是我想做的事情:

/**
 * Creates a function that calls originalFunction, followed by newFunction.
 * The created function returns the value returned by the original function
 * returned by the original function
 * @param originalFunction Function to be called first
 * @param newFunction Function to be called second
 */
function callAfter<T extends Function>(originalFunction: T, newFunction: T): any {
   return function() {
        const result = originalFunction.apply(this, arguments);
        newFunction.apply(this, arguments);
        return result;
   };
}

上面沒有與以下消息一起編譯

TS2322:類型“()=>任何”不能分配給類型“ T”

我有什么辦法可以保持類型安全? 現在,我通過使其返回any來使其“工作”

我進一步嘗試了一下,並提出了以下建議

/**
 * Creates a function that calls originalFunction, followed by newFunction. The created function returns the value
 * returned by the original function
 * @param originalFunction Function to be called first
 * @param newFunction Funct
 */
function callAfter<R, T extends () => R>(originalFunction: T, newFunction: T): T {
    return <T> function () {
        const result: R = originalFunction.apply(this, arguments);
        newFunction.apply(this, arguments);
        return result;
    };
}

這個問題是它對返回void的函數不起作用(這是我目前實際關心的用例)

這是我要編寫的代碼,但是想使用通用的高階函數來擴展功能。

/**
 * Component can use this to have subscriptions automatically
 * removed when the component is removed from the DOM
 */
class SubscriptionTracker {
    private subscriptions: Subscription[] = [];

    constructor(destroyable: OnDestroy) {
        destroyable.ngOnDestroy = callAfter(destroyable.ngOnDestroy, () => {
            this.subscriptions.forEach((subscription) => subscription.unsubscribe());
        });
    }

    subscribe<T>(observable: Observable<T>, observer: PartialObserver<T>): Subscription {
        const subscription = observable.subscribe(observer);
        this.subscriptions.push(subscription);
        return subscription;
    }

    unsubscribe(subscription: Subscription) {
        subscription.unsubscribe();
        const indexOfSubscription = this.subscriptions.indexOf(subscription);
        if (indexOfSubscription == -1) {
            throw new Error('Unsubscribing to untracked subscription');
        }
        this.subscriptions.splice(indexOfSubscription, 1);
        return subscription;
    }
}

據我了解的問題,您只需要對返回類型和參數進行更好的約束。 不必使函子具有相同類型T兩個函數,我們可以為每個函數定義合適的函數類型。

function callAfter<O>(f: (...any) => O, f2: (...any) => void): (...any) => O {
    return (...args) => {
        let r = f(...args);
        f2(...args);
        return r;
    }
}

一些例子:

function  double(x) { return x + x; };

function yell(x) {
    console.log(`${x}!!!`);
}

let doubleLoud = callAfter(double, yell);
let x = doubleLoud(4501);
console.log(`doubleLoud(4501) = ${x}`);

它也可以與在任何一側返回void的函數,甚至具有多個參數的函數一起使用:

callAfter(yell, yell)("Ni");

let lreluLoud = callAfter(function lrelu(x, alpha) {
    if (x < 0) x *= alpha;
    return x;
}, yell);

console.log(`lreluLoud(-20, 0.2) = ${lreluLoud(-20, 0.2)}`);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM