On this page
Functions and Interfaces
Functions and object shapes are the backbone of most TypeScript code. This chapter shows how to annotate them clearly.
Function Types
Annotate parameters and return types:
function add(a: number, b: number): number {
return a + b;
}
const multiply = (a: number, b: number): number => a * b;
function logMessage(msg: string): void {
console.log(msg); // void = no return value
}
Optional and Default Parameters
function greet(name: string, greeting: string = 'Hello'): string {
return `${greeting}, ${name}!`;
}
function buildUrl(path: string, query?: Record<string, string>): string {
if (!query) return path;
const params = new URLSearchParams(query);
return `${path}?${params.toString()}`;
}
console.log(greet('Alice')); // "Hello, Alice!"
console.log(buildUrl('/api/users')); // "/api/users"
console.log(buildUrl('/search', { q: 'ts' })); // "/search?q=ts"
Function Type Expressions
Describe the shape of a function as a type:
type MathOp = (a: number, b: number) => number;
const subtract: MathOp = (a, b) => a - b;
const divide: MathOp = (a, b) => a / b;
function apply(a: number, b: number, op: MathOp): number {
return op(a, b);
}
console.log(apply(10, 4, subtract)); // 6
Interfaces
Interfaces define the shape of objects. They are extendable and work well for class contracts:
interface User {
id: number;
name: string;
email?: string; // optional
readonly createdAt: Date; // cannot be reassigned
}
function displayUser(user: User): void {
console.log(`${user.name} (${user.id})`);
// user.createdAt = new Date(); // Error: readonly
}
const alice: User = {
id: 1,
name: 'Alice',
createdAt: new Date()
};
Extending Interfaces
interface Person {
name: string;
age: number;
}
interface Employee extends Person {
employeeId: string;
department: string;
}
const dev: Employee = {
name: 'Bob',
age: 28,
employeeId: 'E-100',
department: 'Engineering'
};
Type Aliases
Type aliases can represent unions, primitives, or object shapes:
type ID = string | number;
type Point = { x: number; y: number };
type Status = 'pending' | 'active' | 'archived';
function setStatus(id: ID, status: Status): void {
console.log(`User ${id} is now ${status}`);
}
Interface vs Type Alias
| Feature | Interface | Type Alias |
|---|---|---|
| Object shapes | Yes | Yes |
| Extend / merge | Yes (extends, declaration merging) |
Limited |
| Unions / tuples | No | Yes |
| Primitives | No | Yes |
Use interfaces for object contracts; use type aliases for unions, tuples, and utility compositions.
Index Signatures
When object keys are dynamic:
interface StringMap {
[key: string]: string;
}
const translations: StringMap = { hello: 'Hola', goodbye: 'Adiós' };
Typed functions and interfaces make APIs self-documenting and safe to refactor. Next, we explore classes and inheritance.