Skip to content

Return Types

The return type annotation (function f(): T) tells TypeScript what type every return statement in the function must produce. If omitted, TypeScript infers it automatically from the function body β€” but writing it explicitly on public/exported functions acts as a safety net and as documentation for callers.

function double(n: number): number {
return n * 2;
}
function maybeGetUser(id: string): User | undefined {
const user = database.find(id);
return user; // could be User or undefined -- the type says so explicitly
}
async function fetchUser(id: string): Promise<User> {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
function logMessage(message: string): void {
console.log(message); // no meaningful return value
}

Annotating an async function’s return type as the plain value type instead of wrapping it in Promise<T> β€” every async function returns a Promise, regardless of what the return statement inside produces.

// Error: an async function's return type must be Promise<T>
async function fetchUser(id: string): User {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
// Correct
async function fetchUser(id: string): Promise<User> {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
  1. What return type must every async function have, regardless of what value it returns internally?

    AnswerPromise<T>, where T is the type of the resolved value β€” e.g. an async function returning a User must be typed Promise<User>.
  2. What does a return type of void signal?

    AnswerThe function doesn't return a meaningful value β€” callers shouldn't rely on its return value for anything.
  3. Why might you write an explicit return type even though TypeScript could infer it?

    AnswerIt documents the function's contract for readers and callers, and catches accidental changes to the function's behavior during future edits as an immediate compile error rather than a silent type change.