[英]Return typings for dynamic functions
我有一個 function,它唯一的邏輯是執行傳入的 function。
const funcRunner = async (func: Function) => {
return await func()
}
我知道無論傳入的 function 的響應如何,都將是同一個 function 的響應。
然而,這個 function 返回簽名被推斷為Promise<any>
。 有什么辦法可以保留原來function的響應類型?
const bool = async isExample(): Promise<boolean> => true;
// result should be boolean, not any
const result = await funcRunner(isExample);
您可以將其設為通用,這樣 TypeScript 就可以從調用站點推斷出來,並使用實用程序類型ReturnType
來獲取其返回類型:
const funcRunner = async <FuncType extends () => any>(
func: FuncType
): Promise<ReturnType<FuncType>> => {
return await func();
};
使用示例:
async function example1() {
return 1;
}
async function example2() {
return "a";
}
(async() => {
const result1 = await funcRunner(example1);
// ^? const result1: number
const result2 = await funcRunner(example2);
// ^? const result2: string
})();
如果願意,您可以通過不將funcRunner
設為async
來使其更通用一些,然后它可以運行async
或非異步函數,而無需向非async
函數添加async
:
const funcRunner = <FuncType extends () => any>(
func: FuncType
): ReturnType<FuncType> => {
return func();
};
如果您想確保在異步堆棧跟蹤中看到funcRunner
,您可能不想這樣做,但如果您不為此煩惱,那很好。
只是為了好玩:如果你想讓funcRunner
調用需要參數的函數,你可以添加一個完全類型化的args
參數:
async function funcRunner<FuncType extends (...args: any[]) => any>(
func: FuncType,
args: Parameters<FuncType>
): Promise<ReturnType<FuncType>> {
return await func(...args);
}
如果你想讓第二個參數對於不帶任何參數的函數是可選的,我認為你需要重載它:
async function funcRunner<FuncType extends () => any>(
func: FuncType,
): Promise<ReturnType<FuncType>>;
async function funcRunner<FuncType extends (...args: any[]) => any>(
func: FuncType,
args: Parameters<FuncType>
): Promise<ReturnType<FuncType>>;
async function funcRunner<FuncType extends (...args: any[]) => any>(
func: FuncType,
args?: Parameters<FuncType>
): Promise<ReturnType<FuncType>> {
if (args) {
return await func(...args);
}
return await func();
}
重載的用法示例:
async function example1() {
return 1;
}
async function example2() {
return "a";
}
function example3() {
return Math.random() < 0.5;
}
function example4(num: number) {
return num * 42;
}
(async() => {
const result1 = await funcRunner(example1);
// ^?
const result2 = await funcRunner(example2, []); // <=== Args is allowed even when optional...
// ^?
const badResult1 = await funcRunner(example2, ["x"]); // <=== ...but it can't have anything in it
// ^?
const result3 = await funcRunner(example3);
// ^?
const result4 = await funcRunner(example4, [3]);
// ^?
const badResult2 = await funcRunner(example4); // <=== Error as desired, need args!
// ^?
const badResult3 = await funcRunner(example4, ["x"]); // <=== Error as desired, wrong type!
// ^?
})();
當然,您也可以始終使那個async
-neutral; 游樂場鏈接。
可以定義一個泛型來運行 function:
type Runnable<T> = () => Promise<T>;
然后將其應用於您的funcRunner
async function funcRunner<T>(runnable: Runnable<T>): Promise<T> {
return await runnable();
}
您可以選擇使用內聯輸入:
async function funcRunner<T>(runnable: () => Promise<T>): Promise<T> {
return await runnable();
}
用法示例:
async function example1(): Promise<number> {
return 1;
}
funcRunner(example1)
.then((result: number) => console.log(result))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.