02 - Functions

Basic Function Syntax

Type the parameters and the return value:

function add(a: number, b: number): number {
  return a + b;
}

// Arrow function — same thing
const multiply = (a: number, b: number): number => a * b;

The return type is often inferred — you can omit it if it's obvious:

function add(a: number, b: number) {  // return type inferred as number
  return a + b;
}

void and never

// void — function doesn't return anything
function log(message: string): void {
  console.log(message);
}

// never — function never completes (throws or infinite loop)
function throwError(message: string): never {
  throw new Error(message);
}

Optional and Default Parameters

// Optional — might not be passed (becomes undefined)
function greet(name: string, greeting?: string): string {
  return `${greeting || "Hello"}, ${name}`;
}

greet("Alice");           // "Hello, Alice"
greet("Alice", "Hi");     // "Hi, Alice"

// Default — uses a fallback value if not passed
function createUser(name: string, age: number = 18) {
  return { name, age };
}

createUser("Bob");        // { name: "Bob", age: 18 }
createUser("Bob", 25);    // { name: "Bob", age: 25 }

Rest Parameters

Collect any number of arguments into an array:

function sum(...numbers: number[]): number {
  return numbers.reduce((acc, n) => acc + n, 0);
}

sum(1, 2, 3);       // 6
sum(1, 2, 3, 4, 5); // 15

Function Types

Define the shape of a function — useful for callbacks:

type MathOperation = (a: number, b: number) => number;

const divide: MathOperation = (a, b) => a / b;  // types inferred from MathOperation

Callback Types

When a function takes another function as a parameter:

function fetchData(url: string, callback: (data: string) => void): void {
  // ... fetch data
  callback("result");
}

// Or define the callback type separately
type OnComplete = (success: boolean) => void;

function save(data: string, onComplete: OnComplete): void {
  // ... save data
  onComplete(true);
}

Overloads

Same function name, different parameter types:

function format(value: string): string;
function format(value: number): string;
function format(value: string | number): string {
  if (typeof value === "string") {
    return value.toUpperCase();
  }
  return value.toFixed(2);
}

format("hello");  // "HELLO"
format(3.14159);  // "3.14"

Overloads also work with different parameter counts:

function add(a: number, b: number): number;
function add(a: number, b: number, c: number): number;
function add(a: number, b: number, c?: number): number {
  return c !== undefined ? a + b + c : a + b;
}

add(1, 2);      // 3
add(1, 2, 3);   // 6

The implementation signature must be compatible with all overload signatures — that's why c is optional in the implementation above.

⚠️ Important: All overload signatures must appear directly above the implementation with no other code in between.

Key Takeaways

  • Type parameters and return values
  • ? makes a parameter optional, = value gives it a default
  • void = returns nothing, never = never returns
  • Use function types (type Fn = (a: number) => string) for callbacks
  • Let TypeScript infer return types when obvious