Typescript 嵌套函数包装 Return 类型问题
Typescript nested function wrapping Return type problem
我正在调用下面的函数 returns 我 Promise<boolean>
const fnc = (i:number) : Promise<boolean> => Promise.resolve(true)
// Promise<boolean>
const res1 = errorHandler(errorPredicates.sdkError1, fnc, null, 4);
但是,当我将它与另一个错误处理程序嵌套时,返回的对象变为 Promise<any>
// Promise<any>
const res2 = errorHandler(errorPredicates.sdkError1, errorHandler, null, errorPredicates.sdkError2, fnc, null, 4);
下面是重现该问题的示例打字稿代码。我不确定这里有什么问题,或者它是否是打字稿的限制。我该如何解决这个打字问题?
type PromiseFn = (...args: any[]) => Promise<any>;
type UnwrappedReturnType<T extends PromiseFn> = T extends (...args: any) => Promise<infer R> ? R : any
type ThrottlerPredicate = (err: any) => boolean;
type ThrottlerPredicates = {
sdkError1: ThrottlerPredicate
sdkError2: ThrottlerPredicate
}
const errorPredicates: ThrottlerPredicates = {
sdkError1: (err) => err?.message?.search(`429:`) != -1,
sdkError2: (err) => err?.message?.search(`Request was throttled.`) != -1
}
async function errorHandler<ApiFn extends PromiseFn>(
predicate: ThrottlerPredicate,
promiseFunction: ApiFn,
thisArg: ThisParameterType<ApiFn>,
...args: Parameters<ApiFn>
): Promise<UnwrappedReturnType<ApiFn>> {
let errCount = 0
do {
try {
const promiseResult = await promiseFunction.call(thisArg, ...args)
return promiseResult
} catch (err: any) {
//console.error(err)
if (predicate(err)) {
if (errCount < 20)
++errCount;
var ms = 1500 * errCount
} else
throw (err);
}
}
while (true);
}
const fnc = (i:number) : Promise<boolean> => Promise.resolve(true)
// Promise<boolean>
const res1 = errorHandler(errorPredicates.sdkError1, fnc, null, 4);
// Promise<any>
const res2 = errorHandler(errorPredicates.sdkError1, errorHandler, null, errorPredicates.sdkError2, fnc, null, 4);
之所以return类型是Promise<any>
是因为Typecript的泛型需要基于输入参数的类型。因此,res2
中PromiseFunction
的return类型为Promise<UnwrappedReturnType<ApiFn>
。 UnwrappedReturnType
类型需要 PromiseFn
类型的 return 值。此时ApiFn
类型是PromiseFn
的extends,而PromiseFn
类型的return值是Promise<any>
,所以UnwrappedReturnType<ApiFn>
类型是 any
。
同样,用作参数的 errorHandler
泛型 ApiFn
类型与 PromiseFn
((...args: any[]) => Promise) 类型相同,因为有没有预期的参数。
换句话说,如果您指定 ApiFn
通用类型,res2
类型推断是可能的。
...
type ErrorHandler<ApiFn extends PromiseFn> = (
predicate: ThrottlerPredicate,
promiseFunction: ApiFn,
thisArg: ThisParameterType<ApiFn>,
...args: Parameters<ApiFn>
) => Promise<UnwrappedReturnType<ApiFn>>;
// Promise<boolean>
const res2 = errorHandler(errorPredicates.sdkError1, errorHandler as ErrorHandler<typeof fnc>, null, errorPredicates.sdkError2, fnc, null, 4);
很遗憾,我没有理解你想要的功能,所以我根据你的问题进行了回答。如果你能给我解释一下逻辑,我会考虑更好的方法。
我正在调用下面的函数 returns 我 Promise<boolean>
const fnc = (i:number) : Promise<boolean> => Promise.resolve(true)
// Promise<boolean>
const res1 = errorHandler(errorPredicates.sdkError1, fnc, null, 4);
但是,当我将它与另一个错误处理程序嵌套时,返回的对象变为 Promise<any>
// Promise<any>
const res2 = errorHandler(errorPredicates.sdkError1, errorHandler, null, errorPredicates.sdkError2, fnc, null, 4);
下面是重现该问题的示例打字稿代码。我不确定这里有什么问题,或者它是否是打字稿的限制。我该如何解决这个打字问题?
type PromiseFn = (...args: any[]) => Promise<any>;
type UnwrappedReturnType<T extends PromiseFn> = T extends (...args: any) => Promise<infer R> ? R : any
type ThrottlerPredicate = (err: any) => boolean;
type ThrottlerPredicates = {
sdkError1: ThrottlerPredicate
sdkError2: ThrottlerPredicate
}
const errorPredicates: ThrottlerPredicates = {
sdkError1: (err) => err?.message?.search(`429:`) != -1,
sdkError2: (err) => err?.message?.search(`Request was throttled.`) != -1
}
async function errorHandler<ApiFn extends PromiseFn>(
predicate: ThrottlerPredicate,
promiseFunction: ApiFn,
thisArg: ThisParameterType<ApiFn>,
...args: Parameters<ApiFn>
): Promise<UnwrappedReturnType<ApiFn>> {
let errCount = 0
do {
try {
const promiseResult = await promiseFunction.call(thisArg, ...args)
return promiseResult
} catch (err: any) {
//console.error(err)
if (predicate(err)) {
if (errCount < 20)
++errCount;
var ms = 1500 * errCount
} else
throw (err);
}
}
while (true);
}
const fnc = (i:number) : Promise<boolean> => Promise.resolve(true)
// Promise<boolean>
const res1 = errorHandler(errorPredicates.sdkError1, fnc, null, 4);
// Promise<any>
const res2 = errorHandler(errorPredicates.sdkError1, errorHandler, null, errorPredicates.sdkError2, fnc, null, 4);
之所以return类型是Promise<any>
是因为Typecript的泛型需要基于输入参数的类型。因此,res2
中PromiseFunction
的return类型为Promise<UnwrappedReturnType<ApiFn>
。 UnwrappedReturnType
类型需要 PromiseFn
类型的 return 值。此时ApiFn
类型是PromiseFn
的extends,而PromiseFn
类型的return值是Promise<any>
,所以UnwrappedReturnType<ApiFn>
类型是 any
。
同样,用作参数的 errorHandler
泛型 ApiFn
类型与 PromiseFn
((...args: any[]) => Promise
换句话说,如果您指定 ApiFn
通用类型,res2
类型推断是可能的。
...
type ErrorHandler<ApiFn extends PromiseFn> = (
predicate: ThrottlerPredicate,
promiseFunction: ApiFn,
thisArg: ThisParameterType<ApiFn>,
...args: Parameters<ApiFn>
) => Promise<UnwrappedReturnType<ApiFn>>;
// Promise<boolean>
const res2 = errorHandler(errorPredicates.sdkError1, errorHandler as ErrorHandler<typeof fnc>, null, errorPredicates.sdkError2, fnc, null, 4);
很遗憾,我没有理解你想要的功能,所以我根据你的问题进行了回答。如果你能给我解释一下逻辑,我会考虑更好的方法。