How to Type Promises in TypeScript

Use typed promises in TypeScript when async code should guarantee the resolved value shape. This is essential for API calls, database queries, async helpers, and any workflow where the next step depends on reliable types.

What you’ll build or solve

You’ll learn how to type promises in TypeScript with Promise<T>, async functions, and reusable generic helpers. You’ll also know how promise typing improves autocomplete and safety.

When this approach works best

This approach is the right choice when async values need strong type guarantees.

Common real-world scenarios include:

  • API fetch helpers
  • Database queries
  • Auth token loaders
  • File reads
  • Delayed utilities

This is a bad idea when synchronous values are being wrapped unnecessarily just to “look async.”

Prerequisites

You only need:

  • Basic TypeScript types
  • Familiarity with promises
  • Understanding of async/await

Step-by-step instructions

Step 1: Use Promise<T> as the return type

The core syntax is:

function getUser(): Promise<string> {
  return Promise.resolve("Alex");
}

This guarantees the resolved value is a string.

Use the same pattern for arrays and objects.

function getScores(): Promise<number[]> {
  return Promise.resolve([95, 88, 76]);
}

Step 2: Type async functions the same way

Async functions should still use Promise<T>.

async function loadCount(): Promise<number> {
  return 10;
}

Even though the returned value is 10, the real type becomes Promise<number>.

Step 3: Type object-based promise results

This is common for API helpers.

type User = {
  id: number;
  name: string;
};

function fetchUser(): Promise<User> {
  return Promise.resolve({
    id: 1,
    name: "Alex"
  });
}

This makes downstream code strongly typed.

Step 4: Use generic promise helpers

Reusable utilities often return generic promises.

function wrapInPromise<T>(value: T): Promise<T> {
  return Promise.resolve(value);
}

This keeps async helpers flexible.

What to look for:

  • Use Promise<T> for resolved value typing
  • Async functions still return promises
  • Great for APIs and reusable helpers
  • Object promises improve downstream safety
  • Generics keep helpers reusable

Examples you can copy

String result

Promise<string>

User object

Promise<User>

Generic helper

Promise<T>

Common mistakes and how to fix them

Mistake 1: Returning raw values in the type

What the reader might do:

async function load(): number

Why it breaks: async functions always return promises.

Corrected approach:

Use Promise<number>.

Mistake 2: Using any for promise results

What the reader might do:

Promise<any>

Why it breaks: downstream type safety disappears.

Corrected approach:

Define the exact resolved shape.

Mistake 3: Typing the promise object instead of the resolved value

What the reader might do:

Confuse Promise<Response> with parsed JSON data.

Why it breaks: later property access becomes wrong.

Corrected approach:

Type the final resolved data shape.

Troubleshooting

If async functions mismatch, wrap the return type in Promise<T>.

If autocomplete is weak, replace any.

If API parsing changes shape, update the resolved object type.

If helpers should stay generic, use Promise<T>.

Quick recap

  • Use Promise<T> for resolved value types
  • Async functions still return promises
  • Prefer exact object shapes over any
  • Use generics for reusable helpers
  • Type the final resolved data