[英]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.