Promise<T> Async Types

Last updated: 2026-10-22

Promise<T> Async Types

Async types revolve around Promise<T>: an async function's return type is automatically wrapped in a Promise, and await unwraps it at the value level; the utility type Awaited<T> does the same at the type level (unwrapping nested Promises all the way down). Once you know "what type lives inside the Promise", every variable in async code gets a precise type.

GroupEngineering & Practice
KindSyntax
Strict modeNot required

ℹ️ Info The editor transpiles TypeScript to JavaScript and runs it (no type checking); see each example's Output for type-check results.

📝 Syntax

// async functions: the return type is always wrapped in Promise<T>
async function fetchUser(id: number): Promise<User> {
  const res = await getJson("/users/" + id); // await unwraps one layer
  return res;                                 // the returned value is User
}

// Awaited<T>: await at the type level
type A = Awaited<Promise<User>>;        // User
type B = Awaited<Promise<Promise<User>>>; // User, nested promises unwrap too

⚙️ Parameters

Promise<T>A built-in generic container; T is the type of the value you eventually get. Works with async/await out of the box, no imports needed
asyncFunction modifier: allows await inside; the return value is auto-wrapped in a Promise — plain T becomes Promise<T>, existing Promises are not double-wrapped
Awaited<T>Built-in utility type mimicking await: unwraps Promise<T>, recursively unwraps nesting, and passes non-Promise types through unchanged

Returns:An async function returns Promise<T>: whether the body returns a plain T or a Promise<T>, the final type is Promise<T> (never Promise<Promise<T>>).

▶ Example

Edit the code below and click Try it to see the transpiled result:

Output:

{"id":7,"title":"Write TypeScript notes","done":false}
todo#7 title="Write TypeScript notes" done=false

(Runtime output after transpilation; todo is inferred as Todo through await — without await you hold a Promise<Todo>, and todo.id directly is a type error)

💡 Notes

ℹ️ Info Inside an async function, return T and return Promise<T> are exactly equivalent — the type never stacks into Promise<Promise<T>>; Awaited<T> is that rule turned into a utility type.
💡 Tip Promise.all yields a tuple: Promise.all([p1, p2]) has type Promise<[A, B]>, preserving each position's type — one await gets all values with precise individual types.
⚠️ Note A throw inside an async function becomes a rejected Promise rather than a synchronous throw: wrap the await in try/catch or chain .catch(), or you get an unhandled rejection; the Promise<T> return type itself does not reveal possible failure.
More cases coming soon.

📚 Related tutorials

❓ FAQ

Q What does Awaited<T> do and when would I use it?
A It mimics await at the type level: Promise<T> becomes T, nested Promises unwrap fully, non-Promises pass through. You rarely use it directly — it mostly appears inside built-in typings (Promise.all, async return types) and in your own utilities that need to unwrap a Promise, e.g. Unwrap<T> = Awaited<T>.
Q What happens if I forget await?
A You hold a Promise<Todo>, not a Todo: accessing .id is a type error (more obvious under strictNullChecks), and at runtime it is a task that has not finished. TypeScript will not await for you — whenever you see a Promise type, ask whether you need await.
Q Do I have to write Promise<T> explicitly for async functions?
A No — inference derives Promise<T> from the return statements. Writing it explicitly pays off for public APIs (the contract is visible and signature errors surface first); let small internal functions infer.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏