Since TypeScript is a superset of Javascript and ‘Type’ would be removed in the resulting js files, so I guess playing with ‘type’ would not work like this, right?
Also, is there any better way to do it other than having two different methods?
type VoidToVoidFunc = () => void;
type VoidToPromiseVoidFunc = () => Promise<void>;
async function add(func: VoidToVoidFunc | VoidToPromiseVoidFunc) {
if (typeof func == typeof VoidToVoidFunc)
func();
else
await func();
}
add(() => console.log(1));
3
Answers
You’re right, you cannot rely on the type since it’s going to be removed once compiled to JavaScript.
However, you can check the return value of your function. With that, you can check if you should
await
the promise or simply resolve the value.In the case where your function returns a promise, you are
await
-ing it. And in the case it does not, you are simply skipping theawait
part.The following example is in plain JavaScript, to show you how it works.
As you can see here, when a non-thenable value follows
await
, an already-fulfilledPromise
is constructed and used.So the simplest implementation is to
await
the result of the function call. Indeed,await
wraps a value in aPromise
if it’s not already aPromise
:This behavior is correctly typed by TypeScript, indeed when you write
const test = await func();
and hover the variable, its type is correctly inferred tovoid
.TypeScript playground
The cleanest and most maintainable solution is the most strait forward
Playground Link
As you can see from the above, behavior, applying
await
to a non Promise value simply wraps and unwraps it. As youradd
function by virtue of being denotedasync
is necessarily going to return aPromise
and run asynchronously (scheduled on the next tick), more complex solutions offer no benefit in your case.Check out the async function and Promise docs at MDN for further elaboration.
Thus, while there are indeed other ways to determine if a you received a callback that may or may not return a Promise, such as
Playground Link
keeping it simple is the way to go here.
Note:
void
is a TypeScript type expressing the contract of a function and guiding type inference. However, every JavaScript function and thus every TypeScript function actually returns a value. In this casefunc
param ofadd
returns eitherundefined
or aPromise
that resolves toundefined
.