There are two function types, one returns string and other one returns a Promise<string>. Now I'd like to have a function to wrap them, but I have to distinguish each one while invoking fn
type FuncTypes = (...args: any[]) => string | Promise<string>
function callFunc(fn: FuncTypes, ...args: any[]) {
// distinguish fn returns string or Promise<string>
// if fn returns string
return new Promise<string>(r => r(fn.call(this, ...args)))
// if fn returns a Promise
return fn.call(this, ...args)
}
Another situation is overload:
type FuncA = (...args: any[]) => string
type FuncB = (...args: any[]) => Promise<string>
function callFunc(fn: FuncA, ...args: any[]): Promise<string>
function callFunc(fn: FuncB, ...args: any[]): Promise<string>
function callFunc(fn: any, ...args: any[]): Promise<string> {
// if fn is instanceof FuncA
// do sth.
// else if fn is instanceof FuncB
// do sth
}
Although we can simply use const returned = fn(..args); typeof returned === 'string' to check returned type, it is not a general solution. If function type is () => AnInterface|AnotherInterface, it's difficult to check return type by using typeof or instanceof.
Is there any general way to distinguish them? or should I write two functions for each type?