DG
DevGuide
Run Code
Home/TypeScript/Interfaces & Type Aliases
TS TypeScript2 / 4

Interfaces & Type Aliases

📌 WHAT

Interfaces and type aliases define the SHAPE of objects — what properties they must have and their types. Think of them as contracts that objects must fulfill.

💡 WHY

Ensures every object of that 'shape' has required fields, catching missing or wrongly-typed data instantly. Makes APIs self-documenting.

⏰ WHEN / WHERE

For any object with multiple properties: component props, API responses, function parameters, database row shapes.

🔧 HOW

Use interface for object shapes (extensible, can be merged). Use type for unions, primitives, tuples, or when you need advanced type features.

📚Key Terms

Optional property (?)

— Property that may or may not exist: name?: string

Readonly

— Property that cannot be changed after creation: readonly id: number

Union type (|)

— Value can be one of several types: string | number

Intersection type (&)

— Value must satisfy ALL types: TypeA & TypeB

Literal type

— Exact value as a type: 'admin' | 'user' instead of just string

Code Examples

#1interface — object contracts

interface — object contracts
typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Basic interface
interface User {
id: number; // required
name: string; // required
email: string; // required
role?: "admin" | "user"; // ? = optional, literal union type
readonly createdAt: Date; // readonly = cannot change after creation
}
// Using the interface
function greetUser(user: User): string {
return `Hello, ${user.name} (${user.role ?? "user"})`;
}
const u: User = {
id: 1,
name: "Ali",
email: "ali@example.com",
createdAt: new Date(),
// role is optional so we can omit it
};
// u.createdAt = new Date(); // ❌ Error: cannot assign to 'createdAt' — readonly
// Extending interfaces
interface AdminUser extends User {
permissions: string[];
lastLogin: Date;
}
// Implementing multiple interfaces
interface Serializable {
toJSON(): string;
}
interface Printable {
print(): void;
}
interface Document extends Serializable, Printable {
title: string;
content: string;
}

#2type aliases — more flexible

type aliases — more flexible
typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// Type alias for primitives and unions
type ID = string | number;
type Status = "active" | "inactive" | "pending";
type Direction = "up" | "down" | "left" | "right";
// Type alias for objects (similar to interface)
type Point = {
x: number;
y: number;
};
// Intersection types — combine types
type Employee = {
employeeId: number;
department: string;
};
type UserEmployee = User & Employee; // must have ALL fields from both
// Conditional types (advanced)
type IsString<T> = T extends string ? "yes" : "no";
type Result = IsString<string>; // "yes"
// Key differences: interface vs type
// ✅ interface: can be extended with 'extends', can be merged
// ✅ type: can use unions (|), intersections (&), computed types
// Best practice:
// → Use 'interface' for object shapes you'll extend/implement
// → Use 'type' for unions, primitives, tuples, computed types
// Function types
type Formatter = (value: string) => string;
const uppercase: Formatter = (s) => s.toUpperCase();
// Callback type
type OnChange = (event: React.ChangeEvent<HTMLInputElement>) => void;

Practice This Concept

Open the playground, paste any example, and experiment. The best way to learn is by breaking things.

Open in Playground