TypeScript Functions

Functions are where TypeScript's type system delivers the most value. Every parameter, return value, and callback can be typed — giving you autocomplete, error checking, and documentation for free.

Parameter and Return Types

TypeScript
function multiply(a: number, b: number): number {
  return a * b;
}

const result = multiply(3, 4); // 12

The : number after each parameter is the type annotation. The : number after the parentheses is the return type.

You can often omit the return type — TypeScript infers it:

TypeScript
// Return type inferred as number
function multiply(a: number, b: number) {
  return a * b;
}

Best practice: always annotate return types on public functions. They serve as documentation and prevent accidental return type changes.

Optional and Default Parameters

TypeScript
// Optional parameter — must come after required ones
function greet(name: string, greeting?: string): string {
  return `${greeting ?? "Hello"}, ${name}!`;
}

greet("Sita");            // "Hello, Sita!"
greet("Sita", "Namaste"); // "Namaste, Sita!"

// Default parameter
function createUser(name: string, role: string = "student") {
  return { name, role };
}

createUser("Ram");                        // { name: "Ram", role: "student" }
createUser("Sita", "admin");              // { name: "Sita", role: "admin" }

Rest Parameters

Collect any number of arguments into an array:

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

sum(1, 2, 3, 4);       // 10
sum(10, 20, 30);        // 60

Named Arguments (Destructuring)

For functions with many parameters, destructure an object:

TypeScript
interface CreateUserOptions {
  name: string;
  age: number;
  role?: string;
  active?: boolean;
}

function createUser({ name, age, role = "student", active = true }: CreateUserOptions) {
  return { name, age, role, active };
}

createUser({ name: "Sita", age: 21 });
createUser({ name: "Ram", age: 22, role: "admin", active: false });

Function Overloads

When a function accepts different argument shapes and returns different types:

TypeScript
function format(input: string): string;
function format(input: number): string;
function format(input: Date): string;
function format(input: string | number | Date): string {
  if (typeof input === "string") return input.trim();
  if (typeof input === "number") return input.toFixed(2);
  return input.toISOString().split("T")[0];
}

format("  hello  ");           // "hello"
format(3.14159);               // "3.14"
format(new Date());            // "2026-08-23"

Arrow Functions

TypeScript
const double = (n: number): number => n * 2;

const filter = <T>(items: T[], predicate: (item: T) => boolean): T[] =>
  items.filter(predicate);

// Usage
const evens = filter([1, 2, 3, 4, 5], (n) => n % 2 === 0);
// [2, 4]

Callback Types

When passing functions as parameters:

TypeScript
type FetchCallback = (error: Error | null, data?: string) => void;

function fetchData(url: string, callback: FetchCallback): void {
  // ... async work
  callback(null, "result");
}

Pure vs Side-Effect Functions

TypeScript
// Pure — same input always gives same output, no side effects
function add(a: number, b: number): number {
  return a + b;
}

// Side effect — modifies external state
let count = 0;
function increment(): void {
  count++;
}

Prefer pure functions — they are easier to test, debug and reason about.

Tips

  • Always type callback parameters — this is where most bugs hide.
  • Use never for functions that throw or loop forever.
  • Use default parameters over optional parameters when the default makes the call site clearer.
  • Destructure objects in function parameters when there are 3+ args.

Next: classes — object-oriented TypeScript.