Functions are the main boundaries in any program, and their signatures are where TypeScript catches most mistakes.
Annotate each parameter; the return type is inferred but worth stating on exported functions:
function formatPrice(amount: number, currency: string = "EUR"): string { ... }Parameter options:
- Optional:
name?: string— the parameter may be omitted and has typestring | undefinedinside. - Default:
currency = "EUR"— also optional for callers, and the type is inferred from the default. - Rest:
...values: number[]collects remaining arguments into an array.
TypeScript checks calls strictly: too few or too many arguments is an error, unlike plain JavaScript.
A function type describes a callback or a function-valued variable: (item: string, index: number) => boolean. The parameter names are only documentation; the types and positions matter. A callback with fewer parameters is fine where more are offered — that's why arr.forEach(x => ...) works even though forEach passes three arguments.
Return types worth knowing:
void— the function returns nothing meaningful. A callback type returningvoidmay be given a function that returns something; the value is just ignored.never— the function never returns normally (it always throws or loops forever).
Arrow functions and function expressions are typed the same way. When a function is passed directly as an argument, its parameters are contextually typed, so you usually don't annotate them there.
The this parameter is a fake first parameter (function (this: HTMLElement) {}) that declares what this must be; it is erased in the output.
Example
function formatPrice(amount: number, currency = "EUR", note?: string): string {
const text = `${amount.toFixed(2)} ${currency}`;
return note ? `${text} (${note})` : text;
}
function sum(...values: number[]): number {
return values.reduce((a, b) => a + b, 0);
}
// A function type for a callback
type Predicate = (value: string, index: number) => boolean;
const nonEmpty: Predicate = value => value.length > 0; // fewer params is fine
function fail(message: string): never {
throw new Error(message);
}
console.log(formatPrice(9.5), formatPrice(3, "USD", "sale"), sum(1, 2, 3));
console.log(["a", "", "b"].filter(nonEmpty));
// @ts-expect-error -- Expected 1-3 arguments, but got 0
formatPrice();
if (Math.random() > 2) fail("unreachable");Remember
- Always annotate parameters; state return types on exported functions
p?: Tis optional (T | undefinedinside); defaults make parameters optional too- Function types look like
(a: A, b: B) => R void= no useful return value;never= never returns
Watch out for
- Writing
(string) => void— that declares a parameter named string of type any.