TypeScript functions require parameter type annotations (return types are usually inferred), support optional parameters, default values, rest parameters, and function overloads — function type expressions describe callback signatures for higher-order functions.
Function parameters must have explicit type annotations — TypeScript infers return types from the body but cannot infer parameter types.
Optional (param?: type) makes the parameter type | undefined. Default parameters (param = value) infer the type and are optional from the caller.
Describe callback signatures: (params) => ReturnType. Used in type aliases, interfaces, and higher-order function parameters.
Multiple call signatures for one function — provide precise return types based on input types. Implementation signature must be compatible with all overloads.
void means the return value should be ignored (callbacks). never means the function doesn't return at all (throws or infinite loops).
Functions are the primary unit of behavior in JavaScript, and TypeScript provides several ways to describe their types.
Function parameters must be explicitly annotated — TypeScript doesn't infer parameter types (there's nothing to infer from):
function greet(name: string): string {
return `Hello, ${name}`;
}Return types are usually inferred from the function body — explicit annotations are optional but useful for public APIs where you want to guarantee a contract. If the function's implementation accidentally returns the wrong type, the explicit annotation catches it.
Arrow functions follow the same rules: const add = (a: number, b: number): number => a + b;. Type inference works the same way — return type is inferred, parameters need annotations.
Optional parameters use ?: function log(message: string, level?: string). The parameter's type becomes string | undefined. You can't put optional parameters before required ones.
Default parameters provide a fallback value: function log(message: string, level = 'info'). TypeScript infers the type from the default value, so you don't need both ? and a type annotation. Default parameters are optional from the caller's perspective.
Rest parameters collect remaining arguments into a typed array: function sum(...numbers: number[]): number. You can use tuple types for rest parameters when the arguments have different types: function make<T>(...args: [name: string, value: T]). Labeled tuple elements (name:, value:) improve IDE hints.
To describe a function's type (for callbacks, higher-order functions), use type expressions:
type Callback = (error: Error | null, result: string) => void;
type Comparator<T> = (a: T, b: T) => number;Function type expressions use => (not :) for the return type. They can be used in type aliases, interfaces, parameter types, and generic constraints.
Overloads describe multiple call signatures for a single function:
function createElement(tag: 'input'): HTMLInputElement;
function createElement(tag: 'div'): HTMLDivElement;
function createElement(tag: string): HTMLElement;
function createElement(tag: string): HTMLElement {
return document.createElement(tag);
}Overload signatures (the first three lines) define what callers see. The implementation signature (last) must be compatible with all overloads but is not callable directly. Overloads provide more precise return types based on input values.
In modern TypeScript, generic conditional types often replace overloads with less boilerplate.
void vs undefined Returnvoid means the return value should be ignored — callbacks typed as () => void are allowed to return any value (the caller just won't use it). undefined means the function must explicitly return undefined or return nothing. Use void for callbacks, undefined when you need an explicit return type.
never Return TypeFunctions that never return (throw errors, infinite loops) have return type never: function fail(message: string): never { throw new Error(message); }. This is different from void — void returns (with undefined), never doesn't return at all.
Parameters need explicit type annotations; return types are usually inferred. Optional parameters use ?, default parameters infer their type. Function type expressions describe callback signatures with =>. Overloads provide multiple call signatures with more precise return types. void means "ignore the return"; never means the function never returns.
Fun Fact
The void return type in TypeScript has a surprising behavior: a function typed as () => void can actually return any value — TypeScript just ensures the caller doesn't use it. This exists because JavaScript callbacks frequently return values that are ignored (like Array.forEach's callback), and making void strict would break nearly all callback patterns.