Functions, Parameters, and Return Types
Model function inputs and outputs, optional/default/rest parameters, overloads, callbacks, and function types.
Parameter and Return Types
Type function parameters to define the input contract and specify a return type when it improves clarity or protects a public API. TypeScript can infer return types, but explicit annotations are often useful for exported functions and complex logic because they make unintended return changes visible.
Optional parameters use ? and must generally appear after required parameters. Default parameters are optional at the call site. Rest parameters collect remaining arguments into an array. Prefer a single options object when a function has many related optional settings.
type Invoice = { subtotal: number; taxRate: number };
function totalWithTax(invoice: Invoice): number {
return invoice.subtotal * (1 + invoice.taxRate);
}
function greet(name = "there", punctuation = "!"): string {
return `Hello, ${name}${punctuation}`;
}Invoice contract keeps related values together. Defaulted parameters can be omitted by callers and are inferred unless annotated otherwise.- Function parameters are part of the API contract.
- Return annotations can protect exported interfaces.
- Use options objects when positional arguments become hard to read.
Which syntax makes a parameter optional at the call site?
Function Types and Callbacks
A function type describes the parameter list and return type, for example (value: string) => number. It can be assigned to variables, passed as callbacks, and used in object contracts. Under strict function checking, parameter compatibility matters: a callback should not require arguments the caller might not provide.
When defining event handlers, predicates, sorting callbacks, or plugin APIs, type the callback's inputs based on what the caller promises to pass. A callback's return type should describe what the caller actually uses, such as void for side-effect callbacks.
type Formatter = (value: number) => string;
const currencyFormatter: Formatter = (value) =>
`₹${value.toFixed(2)}`;
function renderValues(values: number[], format: Formatter): string[] {
return values.map(format);
}Formatter can be reused anywhere a number-to-string function is required. The map callback receives each number and returns a string.- Function types make callback contracts reusable.
- Match callback parameters to the caller's guaranteed arguments.
voidis appropriate when the caller ignores the callback result.
What does `(value: number) => string` describe?
Optional, Rest Parameters, and Overloads
Use overload signatures when a function supports multiple call shapes and callers should receive a different precise return type based on the arguments. The overload signatures are visible to callers; the implementation signature is used to implement the behavior and must accommodate all overloads.
Do not add overloads merely to avoid a union type. If the input and output relationships are simple, a union or generic function may be clearer. Runtime checks must still implement each promised case; overload declarations do not generate runtime behavior.
function parseValue(value: string): string[];
function parseValue(value: number): number;
function parseValue(value: string | number): string[] | number {
if (typeof value === "string") return value.split(",");
return value * 2;
}
const parts = parseValue("a,b"); // string[]
const doubled = parseValue(4); // numbertypeof.- Overloads describe supported call signatures.
- The implementation must handle every declared case.
- Use overloads when they improve call-site precision.
Do overload signatures themselves create separate runtime implementations?