"async wraps the return; await unwraps the Promise. Two halves of the same operation."
The two halves
async function declares a function whose return is always wrapped in a Promise. await expression inside an async function pauses until the Promise resolves, then resumes with the resolved value. The result: async code reads like synchronous code, but the type system tracks the Promise wrapper across calls.
Implicit return wrapping
Returning a plain value from an async function: TypeScript automatically wraps it in a Promise. async function f(): Promise<number> { return 42 } — the return 42 becomes Promise<number>.
Returning a Promise from an async function: TypeScript flattens it. async function g(): Promise<User> { return fetchUser(1) /* returns Promise<User> */ } — the result is still Promise<User>, not Promise<Promise<User>>. Promises don't nest.
Await on non-Promises
await value where value isn't a Promise just resolves to the value. The runtime wraps it in Promise.resolve internally. This means await 42 is 42. Useful occasionally; rarely written explicitly.