TypeScript Functions

TypeScript lets you describe exactly what goes into a function and what comes out, catching mismatched arguments before your code ever runs.

Typing Function Parameters

In plain JavaScript, a function will happily accept any value you throw at it, and the mistake only shows up at runtime. TypeScript closes that gap by letting you annotate each parameter with a type. Once annotated, the compiler checks every call site against that type and flags anything that doesn't fit.

Basic Parameter Types

function greet(name: string, times: number): string {
  return name.repeat(times);
}

console.log(greet("Hi ", 3));
// greet(42, "x"); // Error: 42 is not a string

Return Types

You can also annotate the return type of a function. Most of the time TypeScript infers this correctly on its own, but writing it explicitly documents intent and protects you if someone edits the function body later and accidentally changes what it returns.

Explicit Return Type

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

function logMessage(message: string): void {
  console.log(message);
}
Note: If a function never returns normally (it always throws or loops forever), you can annotate it with the never type instead of void.

Optional and Default Parameters

Real functions often have parameters that aren't always required. TypeScript supports two ways to express this: optional parameters, marked with a question mark, and default parameters, which supply a fallback value when the caller omits the argument.

  • Optional parameters (name?: type) must come after required ones and can be undefined.
  • Default parameters (name: type = value) are optional automatically and use the default when omitted.
  • A parameter cannot be both optional and have a default value at the same time.
  • Optional and default parameters must appear after all required parameters in the list.

Optional vs Default

function buildUrl(path: string, query?: string): string {
  return query ? `${path}?${query}` : path;
}

function createUser(name: string, role: string = "member"): string {
  return `${name} (${role})`;
}

console.log(buildUrl("/users"));
console.log(createUser("Ana"));

A Realistic Example

Combining these features lets you model a function signature that mirrors a real API call, where some options are required and others have sensible defaults.

FeatureSyntaxWhen to use
Required parametername: stringValue the function cannot work without
Optional parametername?: stringValue that may legitimately be missing
Default parametername: string = "x"Value that should fall back to a sensible default
Return type: ReturnTypeDocuments and enforces what the function produces

Fetch Options Helper

interface FetchOptions {
  retries?: number;
}

function fetchData(url: string, options: FetchOptions = {}): string {
  const retries = options.retries ?? 3;
  return `Fetching ${url} with ${retries} retries`;
}

console.log(fetchData("/api/posts"));
console.log(fetchData("/api/posts", { retries: 5 }));
Note: Prefer default parameters over manually checking for undefined inside the function body — they keep the fallback logic visible right in the signature.

Exercise: TypeScript Functions

How do you mark a function parameter as optional?