Reading — step 1 of 5
Learn
Functions in TypeScript get parameter types and a return type. Annotating them is one of the highest-value things you can do — most bugs are wrong types flowing through function boundaries.
Annotating function declarations
function add(a: number, b: number): number {
return a + b;
}
const multiply = (a: number, b: number): number => a * b;
The return type can be inferred from the body. Annotating it explicitly is still recommended for public APIs — catches mistakes inside the body and documents intent.
Optional parameters
function greet(name: string, greeting?: string): string {
return `${greeting ?? "Hello"}, ${name}!`;
}
greet("Alice"); // OK — greeting omitted
greet("Bob", "Howdy"); // OK
? makes the parameter optional. Inside the function, the type is string | undefined. Optional parameters MUST come after required ones.
Default values
function greet(name: string, greeting: string = "Hello"): string {
return `${greeting}, ${name}!`;
}
With a default, the parameter is implicitly optional, and inside the function it's just string (not string | undefined).
Rest parameters
function sum(...nums: number[]): number {
return nums.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3); // 6
Rest parameters are typed as an array. The caller spreads however many arguments they want.
Function-type aliases
type Predicate = (n: number) => boolean;
const isPositive: Predicate = n => n > 0;
const isEven: Predicate = n => n % 2 === 0;
Giving a callable shape a name makes APIs cleaner. Anywhere you need a number-to-boolean callback, declare it as Predicate.
Using function types in interfaces
interface EventHandler {
onClick(e: MouseEvent): void;
onSubmit: (data: FormData) => boolean;
}
Both method-shorthand and function-property syntax work for declaring callable members.
Returning void vs undefined
function logIt(msg: string): void {
console.log(msg);
// returning is optional
}
void says "the caller shouldn't depend on a return value." The function CAN return undefined, but void-typed functions in callback positions are special — they let you pass functions that return non-void without TypeScript complaining.
never for impossible returns
function throwError(msg: string): never {
throw new Error(msg);
}
function loopForever(): never {
while (true) {}
}
never is the bottom type — it represents "this function never returns normally." Useful for exhaustiveness checks in switch statements.
Function overloads (briefly)
function parse(input: string): number;
function parse(input: string[]): number[];
function parse(input: string | string[]): number | number[] {
return Array.isArray(input) ? input.map(Number) : Number(input);
}
parse("42"); // typed as number
parse(["1", "2"]); // typed as number[]
Multiple signatures + one implementation. The signatures are what callers see; the implementation is hidden. Useful when one function does meaningfully different things based on argument types.
Common mistakes
- Forgetting return type on async functions — should be
Promise<T>, notT. - Required after optional:
function f(a?: string, b: number)is a compile error (TS1016: a required parameter cannot follow an optional one). Optionals come last. - Using
anyfor parameter types — type the actual shape. If genuinely flexible, use a union or generic. - Wrong function-type variance — methods (
onClick(e): void) and function properties (onClick: (e) => void) behave differently in strict mode.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…