🌱BeginnerObject Types & Interfaces

Function Types

Parameter types, return types, optional and default parameters, rest params, overloads, and function type signatures.

Overview

TypeScript brings full type safety to functions. Every parameter can have a type annotation, and the return type can be explicit or inferred. This turns function signatures into contracts callers know exactly what to pass and what they'll get back. **Key features:** - Optional parameters (`?`) and default values (`= defaultVal`) must come after required params - Rest parameters (`...args: Type[]`) typed variadic functions - Function overloads multiple signatures for one implementation, handling different call patterns - Callable types describing function shapes in interfaces and type aliases - `void` for functions with no meaningful return; `never` for functions that always throw

Key Points

  • •Parameter types: `fn(name: string, age: number)`; return type after `)`: `fn(x: number): string`
  • •Optional: `fn(x: number, y?: number)` `y` is `number | undefined`; must follow required params
  • •Default: `fn(x: number, y = 0)` TypeScript infers `y: number` from the default
  • •Rest params: `fn(...items: string[])` typed variadic argument list
  • •Function type alias: `type Handler = (event: Event) => void`
  • •Callable interface: `interface Fn { (x: number): string; }`
  • •Overloads: separate call signatures + one implementation signature (implementation is wider)

Examples

Parameters, optional, and defaults

// All parameter types + return type
function greet(name: string, greeting: string = "Hello"): string {
  return `${greeting}, ${name}!`;
}
console.log(greet("Alice"));           // "Hello, Alice!"
console.log(greet("Bob", "Hi"));       // "Hi, Bob!"

// Optional parameter
function buildUrl(base: string, path?: string, query?: string): string {
  let url = base;
  if (path)  url += path;
  if (query) url += `?${query}`;
  return url;
}
console.log(buildUrl("https://api.com"));                      // "https://api.com"
console.log(buildUrl("https://api.com", "/users"));            // "https://api.com/users"
console.log(buildUrl("https://api.com", "/users", "page=1")); // "https://api.com/users?page=1"

Rest parameters and function type aliases

// Rest parameters
function sum(...numbers: number[]): number {
  return numbers.reduce((acc, n) => acc + n, 0);
}
console.log(sum(1, 2, 3, 4, 5));   // 15

// Function type aliases
type Predicate<T> = (value: T) => boolean;
type Transform<T, U> = (value: T) => U;
type BinaryOp = (a: number, b: number) => number;

const isEven: Predicate<number> = n => n % 2 === 0;
const double: Transform<number, number> = n => n * 2;
const add: BinaryOp = (a, b) => a + b;

console.log([1,2,3,4].filter(isEven));     // [2, 4]
console.log([1,2,3].map(double));          // [2, 4, 6]
console.log(add(3, 4));                    // 7

Function overloads

// Overloads different signatures for different call patterns
function format(value: string): string;
function format(value: number, decimals?: number): string;
function format(value: string | number, decimals?: number): string {
  if (typeof value === "string") {
    return value.trim().toUpperCase();
  }
  return value.toFixed(decimals ?? 2);
}

console.log(format("  hello "));    // "HELLO"
console.log(format(3.14159));       // "3.14"
console.log(format(3.14159, 4));    // "3.1416"

// Overload with object shapes
function createElement(tag: "input"): HTMLInputElement;
function createElement(tag: "div"):   HTMLDivElement;
function createElement(tag: string):  HTMLElement {
  return document.createElement(tag);
}

// TypeScript knows the exact return type:
const input = createElement("input");   // HTMLInputElement
const div   = createElement("div");     // HTMLDivElement

Common Mistakes

  • Placing optional/default parameters before required ones `fn(x?: number, y: string)` is an error; optionals must come last
  • Using `any` in callback types specify exact types: `(err: Error, result: string) => void` not `(err: any, result: any) => void`
  • Overload implementation type too narrow the implementation signature must cover all overload cases

Note

Default parameters are almost always better than optional parameters when you have a sensible default the caller doesn't have to worry about undefined and the function doesn't need an undefined check.

Exercises

Write TypeScript code to solve each exercise. Click Run to compile and execute it right here, then mark as done.

Loading editor…

Completed: 0 / 5 exercises

Knowledge Check

Question 1 of 4

What is the type of an optional parameter `y?: number` inside the function?