Skip to content
beginner Phase 1 · TypeScript Fundamentals

Function Types

Type function parameters, return values, and optional/default parameters.

1h
0 problems
Topic Progress 0%

Function Type Annotations

Function Type Annotations

Basic Function Types

// Explicit parameter and return types
function add(a: number, b: number): number {
  return a + b;
}

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

// Return type inference (usually fine for simple functions)
const subtract = (a: number, b: number) => a - b;

Void Return Type

function logMessage(msg: string): void {
  console.log(msg);
  // no return statement needed
}

// void functions cannot return values
function invalid(): void {
  return 42; // Error
}

Function as Type

// Function type alias
type MathFn = (a: number, b: number) => number;

const add: MathFn = (a, b) => a + b;
const subtract: MathFn = (a, b) => a - b;

// Interface with function method
interface Calculator {
  add(a: number, b: number): number;
  subtract: (a: number, b: number) => number;
}

const calc: Calculator = {
  add: (a, b) => a + b,
  subtract: (a, b) => a - b
};

Optional and Default Parameters

Optional and Default Parameters

Optional Parameters

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

greet('Alice');           // 'Hello, Alice!'
greet('Alice', 'Hi');     // 'Hi, Alice!'

// Explicit undefined
function greet2(name: string, greeting?: string): string {
  return `${greeting || 'Hello'}, ${name}!`;
}

Default Parameters

// Default parameters are optional and have type inferred
function createUser(
  name: string,
  role: string = 'user',
  active: boolean = true
) {
  return { name, role, active };
}

createUser('Alice');            // { name: 'Alice', role: 'user', active: true }
createUser('Bob', 'admin');     // { name: 'Bob', role: 'admin', active: true }
createUser('Carol', 'user', false);

Rest Parameters

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

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

// Rest with other parameters
function log(level: string, ...messages: string[]): void {
  console.log(`[${level}]`, ...messages);
}

log('INFO', 'Server', 'started', 'on', 'port', '3000');

Function Overloads

Function Overloads

Function overloads allow multiple type signatures for a single function.

Basic Overloads

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

format('hello');       // 'HELLO'
format(42);            // '42.00'
format(new Date());    // '2024-01-15T...'

Complex Overloads

function createElement(tag: 'div'): HTMLDivElement;
function createElement(tag: 'span'): HTMLSpanElement;
function createElement(tag: 'input'): HTMLInputElement;
function createElement(tag: string): HTMLElement {
  return document.createElement(tag);
}

const div = createElement('div');   // HTMLDivElement
const span = createElement('span'); // HTMLSpanElement

Overloads vs Union Types

// Union type approach (simpler)
function process(input: string | number): string {
  return typeof input === 'string' ? input.toUpperCase() : input.toString();
}

// Overload approach (better when return types differ)
function process2(input: string): string;
function process2(input: number): number;
function process2(input: string | number): string | number {
  return typeof input === 'string' ? input.toUpperCase() : input * 2;
}

const result1 = process2('hello'); // string
const result2 = process2(5);       // number

Callbacks and Higher-Order Functions

Callback and Higher-Order Functions

Typed Callbacks

// Callback parameter types
function fetchData(
  url: string,
  onSuccess: (data: unknown) => void,
  onError: (error: Error) => void
): void {
  // ...
}

fetchData(
  '/api/users',
  (data) => console.log(data),
  (error) => console.error(error)
);

Higher-Order Functions

// Function that returns a function
function createMultiplier(factor: number): (value: number) => number {
  return (value) => value * factor;
}

const double = createMultiplier(2);
const triple = createMultiplier(3);

double(5);  // 10
triple(5);  // 15

Generic Callbacks

function map<T, U>(array: T[], fn: (item: T, index: number) => U): U[] {
  return array.map(fn);
}

const numbers = [1, 2, 3, 4, 5];
const doubled = map(numbers, (n) => n * 2);          // number[]
const strings = map(numbers, (n) => n.toString());   // string[]

Common Patterns

// Middleware pattern
type Middleware = (
  req: Request,
  res: Response,
  next: () => void
) => void;

function authMiddleware(req: Request, res: Response, next: () => void): void {
  if (req.headers.authorization) {
    next();
  } else {
    res.status(401).json({ error: 'Unauthorized' });
  }
}

// Promise-based callback
function asyncOperation(): Promise<string> {
  return new Promise((resolve) => {
    setTimeout(() => resolve('done'), 1000);
  });
}

asyncOperation().then((result) => console.log(result));