Interfaces and Type Aliases
## Learning Objectives
- Create and use interfaces
- Define optional and readonly properties
- Use function and indexable types
- Understand type aliases
- Know when to use each
## Interface Basics
### Declaration
```typescript
interface Person {
name: string;
age: number;
}
```
### Implementation
```typescript
function greet(person: Person): string {
return `Hello, ${person.name}!`;
}
let user: Person = { name: "Alice", age: 30 };
greet(user); // "Hello, Alice!"
```
## Optional Properties
Properties that may or may not exist:
```typescript
interface User {
name: string;
email?: string;
age?: number;
}
let user1: User = { name: "Bob" };
let user2: User = { name: "Carol", email: "carol@example.com" };
```
## Readonly Properties
Cannot be modified after creation:
```typescript
interface Point {
readonly x: number;
readonly y: number;
}
let point: Point = { x: 10, y: 20 };
// point.x = 15; // Error: Cannot assign to 'x'
```
## Readonly Arrays
```typescript
interface Config {
readonly options: readonly string[];
}
let config: Config = { options: ["a", "b"] };
// config.options.push("c"); // Error
// config.options = ["x"]; // Error
```
## Function Types in Interfaces
### Method Syntax
```typescript
interface MathFunc {
(x: number, y: number): number;
}
const add: MathFunc = (a, b) => a + b;
const multiply: MathFunc = (a, b) => a * b;
add(2, 3); // 5
multiply(2, 3); // 6
```
### Call Signature
```typescript
interface Sum {
(a: number, b: number): number;
description: string;
}
const sum: Sum = (a, b) => a + b;
sum.description = "Addition function";
```
## Index Signatures
Allow arbitrary property names:
```typescript
interface StringMap {
[key: string]: string;
}
let map: StringMap = {};
map["name"] = "Alice";
map["email"] = "alice@example.com";
```
### With Known Properties
```typescript
interface Nested {
[key: string]: number | string;
length: number; // OK: number
name: string; // OK: string | number
}
```
## Interface Inheritance
### Extending Interface
```typescript
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
let dog: Dog = {
name: "Buddy",
breed: "Labrador"
};
```
### Multiple Inheritance
```typescript
interface A {
a: string;
}
interface B {
b: number;
}
interface C extends A, B {
c: boolean;
}
let obj: C = { a: "hello", b: 42, c: true };
```
## Interface for Classes
### Implementing Interface
```typescript
interface Drawable {
draw(): void;
}
class Circle implements Drawable {
radius: number;
constructor(radius: number) {
this.radius = radius;
}
draw(): void {
console.log(`Drawing circle with radius ${this.radius}`);
}
}
```
### Multiple Interfaces
```typescript
interface Printable {
print(): void;
}
interface Serializable {
serialize(): string;
}
class Document implements Printable, Serializable {
print(): void {
console.log("Printing document");
}
serialize(): string {
return JSON.stringify(this);
}
}
```
## Type Aliases
Name for any type:
### Basic Syntax
```typescript
type ID = string | number;
type Point = { x: number; y: number };
type StringArray = string[];
```
### With Generics
```typescript
type Pair = {
first: T;
second: U;
};
let pair: Pair = { first: "age", second: 30 };
```
### Function Types
```typescript
type Callback = (data: string) => void;
function fetchData(callback: Callback): void {
callback("Data loaded");
}
```
## Interface vs Type Alias
### Interface
```typescript
interface User {
name: string;
}
```
### Type Alias
```typescript
type User = {
name: string;
};
```
### When to Use Interface
- Defining object shapes
- Class implementation contracts
- Declaration merging
### When to Use Type Alias
- Union types
- Tuple types
- Primitive aliases
- Complex generic types
## Hybrid Types
Function + object:
```typescript
interface Counter {
(start: number): void;
value: number;
reset(): void;
}
function createCounter(): Counter {
let value = 0;
const counter = ((start: number) => {
value = start;
}) as Counter;
counter.value = 0;
counter.reset = () => { value = 0; };
return counter;
}
```
## Interface Extension of Type
```typescript
type Base = {
id: string;
};
interface Extended extends Base {
name: string;
}
let obj: Extended = { id: "123", name: "Alice" };
```
## Declaration Merging
Interfaces with same name merge:
```typescript
interface Window {
title: string;
}
interface Window {
width: number;
}
// Merged: { title: string; width: number }
```
## Function Properties
```typescript
interface Config {
onLoad: () => void;
onError: (message: string) => void;
data: string[];
}
let config: Config = {
onLoad: () => console.log("Loaded"),
onError: (msg) => console.error(msg),
data: []
};
```
## Summary
- Interfaces define object shapes
- Type aliases name any type
- Use `?` for optional properties
- Use `readonly` for immutable properties
- Interfaces can extend other interfaces
- Classes `implement` interfaces
- Type aliases are better for unions and tuples
- Interfaces support declaration merging
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →