4Programming TypeScript

类与接口

面向对象类型

类接口抽象类访问修饰符

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第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
// - 联合类型、元组、工具类型:用 type

2.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 有什么区别?

设计一个类型安全的插件系统,使用接口定义插件契约。


4/7类与接口
0%