Type the Function That Gets Passed In
Callback Types
Callbacks are functions passed as arguments. Their types describe the parameters the callback receives and what it should return.
What you'll learn
- Type a callback parameter inline
- Use a named type for clarity
- Recognize void return semantics
A callback is a function passed as an argument. Type it like any other function value.
Inline Callback Types
function each<T>(arr: T[], fn: (item: T, index: number) => void) {
for (let i = 0; i < arr.length; i++) fn(arr[i], i);
}
each(["a", "b"], (item, i) => console.log(i, item));
// ^ item: string, i: number — inferred from the array type The callback’s parameter types are inferred from the surrounding function’s type. The user doesn’t need to annotate.
Named Callback Types
For complex callbacks or reusable signatures:
type EventHandler = (event: { type: string; target: HTMLElement }) => void;
function on(name: string, handler: EventHandler) {
// ...
} Void Return — Caller Doesn’t Care
() => void says “the caller doesn’t use the return value”. The
callback CAN return something — the caller just won’t read it.
type Listener = () => void;
const fn: Listener = () => 42; // ✓ — returning 42 is fine; caller ignores it This is why you can use arr.forEach(item => arr2.push(item))
even though push returns a number — forEach’s callback type is
(...) => void.
When to Annotate the Callback Implementation
You rarely need to annotate the callback’s parameter types when it’s inline — the surrounding signature provides them.
items.map(item => item.name);
// ^ no annotation needed — TS knows item from the array's type Callbacks That Receive Values With Types
type Result<T> = (err: Error | null, data: T | null) => void;
function getUser(id: string, cb: Result<User>) {
// ...
}
getUser("1", (err, data) => {
if (err) return;
console.log(data?.name);
}); Node-style error-first callback, typed.
Up Next
this inside a function — typing it explicitly.