TypeScript Tutorial · TypeScript in Practice · Lesson 23 of 25

TypeScript Async and Promises

Type async functions, Promise<T>, fetch responses and errors in catch.

Promise<T>

An async function returns Promise<T>, where T is the value it resolves to:

Example 1Try it yourself
const wait = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));

async function loadNumbers(): Promise<number[]> {
  await wait(50);
  return [1, 2, 3];
}

const [nums, label] = await Promise.all([loadNumbers(), Promise.resolve("done")]);
console.log(nums.map((n) => n * 2), label);

Output

[ 2, 4, 6 ] done

Typing API data

response.json() returns Promise<any> — the compiler can't know what the server sends. Give the result a type (and ideally validate it at runtime with a library like Zod):

interface Todo { id: number; title: string; completed: boolean }

async function getTodo(id: number): Promise<Todo> {
  const res = await fetch(`https://api.example.com/todos/${id}`);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return (await res.json()) as Todo;
}

Errors are unknown

In a catch block the error has type unknown (with strict), because anything can be thrown. Narrow it before use:

Example 2Try it yourself
async function parsePrice(text: string): Promise<number> {
  const value = Number(text);
  if (Number.isNaN(value)) throw new Error(`"${text}" is not a number`);
  return value;
}

for (const input of ["19.99", "abc"]) {
  try {
    console.log(await parsePrice(input));
  } catch (err: unknown) {
    const message = err instanceof Error ? err.message : String(err);
    console.log("Failed:", message);
  }
}

Output

19.99
Failed: "abc" is not a number

Test yourself

What is the type of err in catch (err) under strict mode?

  1. any
  2. Error
  3. unknown
  4. never
Show answer

Answer: unknown

Practice next