Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript async function return type void vs Promise<void>

Tags:

typescript

Is there a difference between typescript void and Promise< void > types?

Asking because I got confused why this is a valid typescript?

const asyncFunc: () => void = async () => {
    await new Promise(resolve => resolve());
};

Shouldn't this be the only valid case?

const asyncFunc: () => Promise<void> = async () => {
    await new Promise(resolve => resolve());
};
like image 397
zimex Avatar asked Jan 09 '20 13:01

zimex


People also ask

What does promise void mean in TypeScript?

When a function definition has a void return type, it means the function must not return anything. If you need to resolve the Promise with a value of another type, pass the specific type to the generic. index.ts.

What is promise void?

promise<void> may be used to create future<void> objects which have no value. In addition, a promise<void> can be constructed from a promise<T> where T is any type. This allows a promise<void> to be used by code which only needs to be able to renege on a promise and not fulfill it.

What is return type void TypeScript?

According to the TypeScript docs: void represents the return value of functions which don't return a value. Whenever you see a function returning void , you are explicitly told there is no return value. All functions with no return value have an inferred return type of void .

What is return type of promise in TypeScript?

Use the Awaited utility type to get the return type of a promise in TypeScript, e.g. type A = Awaited<Promise<string>> . The Awaited utility type is used to recursively unwrap Promises and get their return type.


Video Answer


3 Answers

Yes there's a difference

void is a little like the opposite of any: the absence of having any type at all. You may commonly see this as the return type of functions that do not return a value

I guess Promise<void> doesn't require explanation.


Now why the assignment in the question is allowed? Because target function (() => void) can be called in all (*almost) the same situations as the source function. Have a look at simplified example:

declare let voidFunc: () => void;
declare let promiseFunc: () => Promise<void>;

voidFunc = promiseFunc; // OK
promiseFunc = voidFunc; // Error: Type 'void' is not assignable to type 'Promise<void>'
like image 86
Aleksey L. Avatar answered Oct 17 '22 16:10

Aleksey L.


When you declare a variable with () => void type, you are basically saying that it could be any function. So its value (function) could return anything. Take a look at this playground. I put there a few more function implementations to you to see that declaring a variable that receives a function is different than declaring a function itself. Declaring the function itself has the behavior you expected.

const asyncFunc: () => void = async () => {
    await new Promise(resolve => resolve());
};

const asyncFunc2: () => Promise<void> = async () => {
    await new Promise(resolve => resolve());
};

const asyncFunc3 = async () => {
    await new Promise(resolve => resolve());
};

// TS compiler complains about it
async function asyncFunc4(): void {
    await new Promise(resolve => resolve());
}

async function asyncFunc4(): Promise<void> {
    await new Promise(resolve => resolve());
}

Edit: Found this little explanation. It could help you understand it too. It says:

Do use the return type void for callbacks whose value will be ignored. Why: Using void is safer because it prevents you from accidentally using the return value of x in an unchecked way

like image 22
Pedro Mutter Avatar answered Oct 17 '22 18:10

Pedro Mutter


This will work as well (notice that this is not even an async function):

const asyncFunc: () => void = () => {
  return Math.random() > 0.5 ? 'hello' : 'world';
};

// OR this:
const asyncFunc2: () => void = () => {
  return { nice: 'very '};
};

why?? Basically, you can have typescript interpret the types itself, or you can set a specific type to a constant.

Here, you defined a constant called asyncFunc, which is of type () => void. This means that typescript will disregard the return value of the function when defining the type. Think of it as if the user don't expect a value, so returning a value should still work fine and not break the code.

So, what's the type of asyncFunc??

If you define the type of the constant yourself, the type will be () => void, so the user won't expect any return value: enter image description here

But if you let typescript interpret this itself, it should know the correct value. So, for the function defined above (without the async), it will be () => string:

enter image description here

So what should you do?

specifically for the case of defining a function as () => void, the function won't check the return value at all and you can return anything (even a promise). Defining a function as async will just wrap the return value in a promise, which the () => void type will just ignore.

If you want to define a different type of the return value than the interpreted type, you can define an async function to return a specific promise with a nested type.

Something like this for your example:

const asyncFunc: () => Promise<void> = async () => {
    await new Promise(resolve => resolve());
};

The thing is, that this will happen automatically without the type definition: enter image description here

So it's pretty redundant. you can just let typescript interpret the types unless you want to change the return type to something else.

So, in the example that might return hello or world we might want to let the user know that the return value can be any string instead of these two values. Then, it makes sense to change the definition of the return value to something else: enter image description here

You can combine any of these to achieve a workflow you like, but be aware that () => void is kind of a special case with this type system (since any other return value besides void will throw a type error.

like image 5
Thatkookooguy Avatar answered Oct 17 '22 16:10

Thatkookooguy