TS Return Types
Return type annotations turn "what does this give back?" into a compiler-checked contract. Most of the time TS infers them — you write them for the boundaries that matter.
Explicit
TS
function add(a: number, b: number): number {
return a + b;
}
Inferred
TS
function double(x: number) {
return x * 2; // inferred: number
}
void — no useful return
TS
function log(msg: string): void {
console.log(msg);
}
Never — function doesn't return
TS
function fail(msg: string): never {
throw new Error(msg);
}
Union returns
TS
function divide(a: number, b: number): number | null {
if (b === 0) return null;
return a / b;
}
Async returns
An async function always returns a Promise<T>:
TS
async function getUser(id: number): Promise<User> {
const res = await fetch(`/api/users/${id}`);
return res.json();
}
When to annotate
| Annotate | Skip (let TS infer) |
|---|---|
| Exported functions / public APIs | Small inline callbacks |
| Functions you want to prevent changing | Single-expression arrow functions |
| Functions returning unions | Functions delegating to a well-typed helper |
Tip: Turn on
noImplicitReturns in tsconfig — TS will warn if a function has paths that don't return when others do. Catches "forgot to return inside the if".Example
Example
function divide(a: number, b: number): number | null {
if (b === 0) return null;
return a / b;
}
const r = divide(10, 0);
if (r !== null) console.log(r.toFixed(2));
Try it Yourself »
Exercise
Annotate the return type as a Promise of User.
async function getUser():
{}
PascalCase wrapper around User.
Discussion
Loading…