第4章:类与接口(Classes and Interfaces)
一、导读
1.1 本章学习目标
第4章讲解 TypeScript 的面向对象类型系统——类和接口的类型化方式。
本章的核心学习目标包括:
- 掌握 TypeScript 类的类型系统:访问修饰符、抽象类、类类型
- 深入理解接口(interface):接口合并、扩展接口、接口 vs 类型别名
- 掌握类与接口的关系:
implements关键字、接口作为契约 - 理解 TypeScript 的类与 JavaScript 类的区别
1.2 为什么本章如此重要
TypeScript 的类和接口是构建大型应用的基础。接口定义了模块之间的契约,类实现了这些契约。理解它们的类型系统,才能设计出灵活且类型安全的面向对象架构。
1.3 核心问题引导
interface 和 type 有什么区别?什么时候用哪个?
TypeScript 的访问修饰符(public、private、protected)与 Java 的有什么区别?
什么是接口合并(declaration merging)?它有什么实际用途?
类如何实现接口?一个类可以实现多个接口吗?
二、核心概念详解
2.1 类
typescript
class Animal {
// 访问修饰符
public name: string;
private age: number;
protected species: string;
// readonly 属性
readonly id: string;
// 参数属性(简写)
constructor(name: string, age: number, species: string, id: string) {
this.name = name;
this.age = age;
this.species = species;
this.id = id;
}
// 简写形式
// constructor(
// public name: string,
// private age: number,
// protected species: string,
// readonly id: string
// ) {}
speak(): string {
return `${this.name} makes a sound`;
}
}
class Dog extends Animal {
speak(): string {
return `${this.name} barks`;
}
}2.1.1 抽象类
typescript
abstract class Shape {
abstract area(): number;
abstract perimeter(): number;
describe(): string {
return `Shape with area ${this.area().toFixed(2)}`;
}
}
class Circle extends Shape {
constructor(private radius: number) { super(); }
area(): number { return Math.PI * this.radius ** 2; }
perimeter(): number { return 2 * Math.PI * this.radius; }
}2.2 接口
typescript
interface User {
readonly id: string;
name: string;
email?: string;
age: number;
}
// 接口扩展
interface Admin extends User {
permissions: string[];
level: number;
}
// 接口合并
interface Window {
title: string;
}
interface Window {
width: number;
}
// 合并后: { title: string; width: number }2.2.1 interface vs type
typescript
// interface:适合对象形状、可合并、可 extends
interface User {
name: string;
}
// type:更灵活、支持联合类型、映射类型等
type StringOrNumber = string | number;
type Pair<T> = [T, T];
type Callback = (data: string) => void;
// 经验法则:
// - 定义对象形状:优先 interface
// - 联合类型、元组、工具类型:用 type2.3 类实现接口
typescript
interface Serializable {
serialize(): string;
deserialize(data: string): void;
}
interface Printable {
print(): void;
}
class Document implements Serializable, Printable {
constructor(private content: string) {}
serialize(): string {
return JSON.stringify({ content: this.content });
}
deserialize(data: string): void {
const parsed = JSON.parse(data);
this.content = parsed.content;
}
print(): void {
console.log(this.content);
}
}三、实战案例
3.1 案例一:类型安全的构建器模式
typescript
interface HttpRequestConfig {
url: string;
method: "GET" | "POST" | "PUT" | "DELETE";
headers: Record<string, string>;
body?: unknown;
timeout: number;
}
class HttpRequestBuilder {
private config: Partial<HttpRequestConfig> = {};
setUrl(url: string): this {
this.config.url = url;
return this;
}
setMethod(method: HttpRequestConfig["method"]): this {
this.config.method = method;
return this;
}
setHeader(key: string, value: string): this {
this.config.headers = { ...this.config.headers, [key]: value };
return this;
}
setBody(body: unknown): this {
this.config.body = body;
return this;
}
setTimeout(ms: number): this {
this.config.timeout = ms;
return this;
}
build(): HttpRequestConfig {
if (!this.config.url) throw new Error("URL is required");
if (!this.config.method) throw new Error("Method is required");
return {
url: this.config.url,
method: this.config.method,
headers: this.config.headers ?? {},
body: this.config.body,
timeout: this.config.timeout ?? 30000
};
}
}
const request = new HttpRequestBuilder()
.setUrl("/api/users")
.setMethod("POST")
.setHeader("Content-Type", "application/json")
.setBody({ name: "Alice" })
.setTimeout(5000)
.build();四、本章小结
类:访问修饰符、readonly、参数属性、抽象类。
接口:可选属性、readonly、接口扩展、接口合并。
interface vs type:interface 适合对象形状,type 更灵活。
类实现接口:implements 关键字,支持多接口。
五、思考与练习
interface 和 type 的核心区别是什么?在大型项目中如何选择?
TypeScript 的 private 和 JavaScript 的 #private 有什么区别?
设计一个类型安全的插件系统,使用接口定义插件契约。