DEV Community

Cover image for React + TypeScript: async functions
Arka Chakraborty
Arka Chakraborty

Posted on

React + TypeScript: async functions

When working with TypeScript, one of the most common confusions is around asyncfunctions and their return types. Let’s clear this up with a practical example.


📝A Practical Example: Checking If a User Is Logged In

Imagine you’re building an app where you need to check if a user is logged in.

Synchronous version

function isUserLoggedIn(): boolean {
  return true;
}

Enter fullscreen mode Exit fullscreen mode

This works fine if the answer is always available instantly.

Asynchronous version

But in real-world apps, login status often comes from a server or database:

async function isUserLoggedIn(): Promise<boolean> {
  const response = await fetch("/api/check-login");

  if (!response.ok) {
    return false;
  }

  const data = await response.json();
  return data.loggedIn; // true or false
}

Enter fullscreen mode Exit fullscreen mode

Notice:

  • The return type is Promise<boolean> (not boolean).
  • Even though we return trueor false, the value is wrapped in a Promise.

❓Why Promise and not boolean?

Every asyncfunction in TypeScript always returns a Promise.

So this:

return true;

Enter fullscreen mode Exit fullscreen mode

is really:

return Promise.resolve(true);

Enter fullscreen mode Exit fullscreen mode

That’s why the return type must be Promise<boolean>.

If you mistakenly annotate it as just boolean:

async function isUserLoggedIn(): boolean {
  return true;
}

Enter fullscreen mode Exit fullscreen mode

You’ll get a compile error:

Type 'boolean' is not assignable to type 'Promise<boolean>'.

Enter fullscreen mode Exit fullscreen mode

📝Using the Async Function

// With await
const loggedIn = await isUserLoggedIn();
console.log(loggedIn); // true or false

// Or with .then()
isUserLoggedIn().then(status => console.log(status));

Enter fullscreen mode Exit fullscreen mode

⚠️Misconception: Isn’t This Synchronous Because of await?

A common doubt: “If we’re awaiting, aren’t we back to synchronous execution?”

Answer: No.

  • awaitpauses execution only in the current function until the Promiseresolves.
  • But it does not block the event loop. Other tasks can keep running.

So:

  • Asyncfunctions are still asynchronous under the hood.
  • awaitjust gives you synchronous-looking syntax for cleaner code.

Example:

async function main() {
  console.log("Before");
  await isUserLoggedIn(); // pauses *this* function only
  console.log("After");
}

main();
console.log("Outside");

Enter fullscreen mode Exit fullscreen mode

Output order:

Before
Outside
After

Enter fullscreen mode Exit fullscreen mode

Notice how "Outside" runs while we were “waiting.” That’s the power of async/await.


📌Async Arrow Functions

asyncworks seamlessly with arrow functions. This is very common in modern TypeScript and React projects.

Example with arrow function

const isUserLoggedIn = async (): Promise<boolean> => {
  const response = await fetch("/api/check-login");
  const data = await response.json();
  return data.loggedIn;
};

Enter fullscreen mode Exit fullscreen mode

In a React handler

const handleSubmit = async (event: React.FormEvent) => {
  event.preventDefault();

  const success = await isUserLoggedIn();
  console.log("Login status:", success);
};

Enter fullscreen mode Exit fullscreen mode

With array methods

Arrow functions and asyncoften pair with array operations:

const urls = ["/a", "/b", "/c"];

const fetchAll = async () => {
  const results = await Promise.all(
    urls.map(async url => {
      const res = await fetch(url);
      return res.json();
    })
  );

  console.log(results);
};

Enter fullscreen mode Exit fullscreen mode

💡Key Takeaways

  • asyncfunctions always return Promise<T>, never just T.
  • Returning a raw value auto-wraps it in Promise.resolve(value).
  • awaitpauses locally but doesn’t block the event loop.
  • Async arrow functions are common in callbacks, handlers, and array methods.
  • Use asyncwhen dealing with APIs, databases, or any future async work — it future-proofs your function signatures.

Top comments (0)