Recently, I encountered a challenge with wrapper function types.
I am looking to convert functions with callbacks into promise-based functions. Most of these functions have a similar structure:
func({
success:....,
fail:....,
complete:...
})
So, I created a wrapper function:
function toAsync<
OptType
SuccesResType,
FailResType>(fn:(opt:OptType)=>any):(opt:OptType)=>Promise<SuccesResType>{
return async (opt:OptType):Promise<SuccesResType>=>{
return new Promise<SuccesResType>((resolve,reject)=>{
fn({
...(opt || {}),
success(res:SuccesResType){
resolve(res)
},
fail(res:FailResType){
reject(res)
}
} as unknown as OptType)
})
}
}
However, I faced an issue where the SuccessResType
represents the parameter type of opt.success
, and FailResType
is for opt.fail
.
My problem lies in defining the correct type hint for my toAsync
wrapper function when using it like this:
const fn = toAsync(fn)
Instead of repeating certain steps such as:
type fnOptType = Parameters<typeof fn>[0]
type fnSuccessRestype = Parameters<fnOptType.SuccessCallback>[0]
type fnFailResType = Parameters<fnOptType.FailCallback>[0]
type fn = toAsync<fnOptType,fnSuccessRestype,fnFailResType>(fn)
Currently, if I use toAsync
like const fn = toAsync(fn)
, no hint option will be provided unless I manually specify the generic type.
Update:
For fn
, its option type can vary, such as:
function request(opt:{
fail?:(res:RequestFailResType)=>any;
success?:(res:RequestSuccessResType)=>any;
complete?:(res:RequestCompleteResType)=>any;
url:string
}):any{
// do things here
}
function locationQuery(opt:{
fail?:(res:QueryFailResType)=>any;
success?:(res:QuerySuccessResType)=>any;
complete?:(res:QueryCompleteResType)=>any;
lat:number,
log:number
}):any{
// do things here
}
toAsync
needs to accommodate these type variations, which appears to be quite a significant compatibility requirement.
Considering the numerous functions I have structured in this way, I am seeking a more efficient method for achieving backward type support.