Typing Functions in TypeScript
Parameter types, return types, optional parameters, and function type expressions.
2 min read
Functions are where TypeScript's type checking earns its keep most immediately — a wrong argument type is caught at every call site, not just the one that happens to trigger a bug at runtime.
Parameter and return types
function add(a: number, b: number): number {
return a + b;
}
add(2, 3); // 5
add(2, "3"); // Argument of type 'string' is not assignable to parameter of type 'number'The return type (: number after the parameter list) is usually inferable and can be omitted, but writing it explicitly on exported/public functions is good practice — it documents the contract and catches the case where a later edit accidentally changes what the function returns.
function add(a: number, b: number) {
return a + b; // return type inferred as number
}Optional parameters
A ? marks a parameter as optional — it can be omitted by the caller, and its type includes undefined automatically:
function greet(name: string, greeting?: string): string {
return `${greeting ?? "Hello"}, ${name}!`;
}
greet("Ada"); // "Hello, Ada!"
greet("Ada", "Hi"); // "Hi, Ada!"Optional parameters must come after required ones in the parameter list — TypeScript enforces this so a call can't be ambiguous about which argument was omitted.
Default parameters
function greet(name: string, greeting: string = "Hello"): string {
return `${greeting}, ${name}!`;
}A default value makes the parameter optional automatically, and TypeScript infers its type from the default (string, in this case) if you don't annotate it explicitly.
Function type expressions
A variable can be typed as "a function that takes these parameters and returns this" — useful for callbacks and higher-order functions:
let multiply: (a: number, b: number) => number;
multiply = (a, b) => a * b; // parameter types inferred from the variable's own type
function applyOperation(a: number, b: number, operation: (a: number, b: number) => number): number {
return operation(a, b);
}
applyOperation(4, 5, multiply); // 20Note that inside applyOperation, the operation parameter itself only needs its type written once — TypeScript then infers the types of a and b inside the arrow function passed as multiply from that context, a pattern called contextual typing.
void for functions that don't return a value
function logMessage(message: string): void {
console.log(message);
}void signals the return value isn't meant to be used — distinct from a function explicitly returning undefined, though TypeScript treats them compatibly in most situations.
With functions covered, the next lesson moves to describing the shape of objects directly with interface — the more common way to type the kind of structured data functions actually operate on.