Functions¶
Functions are the heart of any JavaScript application. TypeScript enhances them by letting you explicitly describe:
- what parameters a function expects
- what it returns
- how it behaves in different call scenarios
- whether it returns nothing (
void) or never returns at all (never)
This transforms functions from “flexible but risky” to “precise and self‑documenting.”
Parameter Types¶
In JavaScript, function parameters are untyped. TypeScript lets you specify exactly what each parameter should be.
function greet(name: string, age: number) {
return `${name} is ${age} years old`
}
If you call it incorrectly:
greet("Alice", "30") // ❌ Error
greet(123, 456) // ❌ Error
Optional parameters¶
Use ? to mark parameters as optional:
function log(message: string, prefix?: string) {
console.log(prefix ? `${prefix}: ${message}` : message)
}
Default parameters¶
Default values automatically infer types:
function multiply(a: number, b = 1) {
return a * b
}
Return Types¶
TypeScript can infer return types, but explicitly annotating them improves clarity and prevents accidental changes.
function add(a: number, b: number): number {
return a + b
}
If you accidentally return the wrong type:
function add(a: number, b: number): number {
return "not a number" // ❌ Error
}
Why explicitly annotate return types?¶
- Prevents accidental return type changes
- Makes refactoring safer
- Improves readability and API clarity
Function Overloads¶
JavaScript functions often behave differently depending on the arguments passed. TypeScript lets you model this with overloads.
Example: A function that returns different types¶
function format(input: string): string
function format(input: number): string
function format(input: string | number): string {
return `Value: ${input}`
}
Usage:
format("hello") // ✔ OK
format(123) // ✔ OK
format(true) // ❌ Error
Why overloads matter¶
They allow you to express:
- multiple valid call signatures
- different return types based on input
- more precise type checking
This is especially useful for:
- parsing functions
- utility libraries
- DOM APIs
- data transformation functions
void vs never¶
These two special return types often confuse newcomers, but they serve very different purposes.
void — A function that returns nothing¶
function log(message: string): void {
console.log(message)
}
void means:
- the function may return
undefined - callers should not expect a value
It’s the correct type for:
- logging
- event handlers
- callbacks that don’t return anything
never — A function that never returns¶
A function returns never when it cannot return normally.
1. Functions that always throw¶
function fail(message: string): never {
throw new Error(message)
}
2. Functions with infinite loops¶
function loopForever(): never {
while (true) {}
}
3. Exhaustiveness checking¶
never is essential for catching missing cases:
type Shape = { kind: "circle" } | { kind: "square" }
function area(shape: Shape) {
switch (shape.kind) {
case "circle":
return 1
case "square":
return 2
default:
const _exhaustive: never = shape // ❌ Error if a case is missing
return _exhaustive
}
}
Summary: void vs never¶
| Type | Meaning | Example |
|---|---|---|
void |
Function returns nothing | Logging, event handlers |
never |
Function never returns | Throws, infinite loops, exhaustiveness checks |
Summary¶
In this lesson, you learned how TypeScript enhances functions with:
1. Parameter types¶
- required, optional, and default parameters
2. Return types¶
- explicit annotations for clarity and safety
3. Function overloads¶
- multiple call signatures for flexible APIs
4. void vs never¶
void→ returns nothingnever→ never returns at all
These tools make your functions predictable, self‑documenting, and far safer than their JavaScript counterparts.