I'm making this silly function that will make a try/catch for any function and return it as a tuple with data and error
export type CatchReturn<T> = [data: T | undefined, error: unknown | undefined];
export const tcatch = <T>(
tryFunc: (() => T) | (() => Promise<T>)
) => {
try {
const res = tryFunc();
if (res instanceof Promise) {
return res
.then<CatchReturn<T>>((r) => [r, undefined])
.catch<CatchReturn<T>>((e) => [undefined, e]);
} else {
return [res, undefined] as CatchReturn<T>;
}
} catch (e) {
return [undefined, e] as CatchReturn<T>;
}
};
The function works as expected, but what I'm not able to do is correctly type the return type.
At the moment, the return type is CatchReturn<T> | Promise<CatchReturn<T>> but I wanted the return type to only be CatchReturn<T> if tryFunc: (() => T) and Promise<CatchReturn<T>> only if tryFunc: (() => Promise<T>).
So for example:
How it's working at the moment
const syncRes = tcatch(() => {}) // return type is CatchReturn<T> | Promise<CatchReturn<T>>
const asyncRes = tcatch(async () => {}) // return type is CatchReturn<T> | Promise<CatchReturn<T>>
How I expect it to work
const syncRes = tcatch(() => {}) // return type should be CatchReturn<T>
const asyncRes = tcatch(async () => {}) // return type should be Promise<CatchReturn<T>>
I tried using conditional types in the return type, but always got errors and I'm not 100% sure if this is even possible.