Skip to content
On this page

TypeScript 接口与类

TypeScript 的接口和类提供了面向对象编程的强大功能,使代码更加结构化和可维护。

接口(Interface)

接口是 TypeScript 的核心特性之一,用于定义对象的结构和契约。

基本接口

typescript
interface User {
  name: string;
  age: number;
  email?: string; // 可选属性
  readonly id: number; // 只读属性
}

const user: User = {
  name: "Alice",
  age: 25,
  id: 12345
};

// user.id = 123; // 错误:不能修改只读属性

函数类型接口

typescript
interface SearchFunc {
  (source: string, subString: string): boolean;
}

let mySearch: SearchFunc = function(source: string, subString: string): boolean {
  let result = source.search(subString);
  return result > -1;
};

可索引类型

typescript
interface StringArray {
  [index: number]: string;
}

let myArray: StringArray = ["Bob", "Fred"];

interface NumberDictionary {
  [index: string]: number;
  length: number;    // 可以,length 是 number 类型
  name: string;      // 错误,name 的类型与索引类型不匹配
}

继承接口

typescript
interface Shape {
  color: string;
}

interface Square extends Shape {
  sideLength: number;
}

let square: Square = {
  color: "blue",
  sideLength: 10
};

// 多重继承
interface PenStroke {
  penWidth: number;
}

interface Square2 extends Shape, PenStroke {
  sideLength: number;
}

let square2: Square2 = {
  color: "blue",
  sideLength: 10,
  penWidth: 5.0
};

混合类型

typescript
interface Counter {
  (start: number): string;
  interval: number;
  reset(): void;
}

function getCounter(): Counter {
  let counter = <Counter>function (start: number) { };
  counter.interval = 123;
  counter.reset = function () { };
  return counter;
}

let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;

类(Class)

TypeScript 完全支持 ES6 的类语法,并添加了额外的功能。

基本类

typescript
class Greeter {
  greeting: string;
  
  constructor(message: string) {
    this.greeting = message;
  }
  
  greet(): string {
    return "Hello, " + this.greeting;
  }
}

let greeter = new Greeter("world");

继承

typescript
class Animal {
  name: string;
  constructor(theName: string) { this.name = theName; }
  move(distanceInMeters: number = 0) {
    console.log(`${this.name} moved ${distanceInMeters}m.`);
  }
}

class Snake extends Animal {
  constructor(name: string) {
    super(name); // 派生类的构造函数必须调用 super()
  }
  move(distanceInMeters = 5) {
    console.log("Slithering...");
    super.move(distanceInMeters);
  }
}

class Horse extends Animal {
  constructor(name: string) { super(name); }
  move(distanceInMeters = 45) {
    console.log("Galloping...");
    super.move(distanceInMeters);
  }
}

let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);

公共和私有修饰符

typescript
class Animal2 {
  private name: string;
  constructor(theName: string) { this.name = theName; }
}

// new Animal2("Cat").name; // 错误: 'name' 是私有的

// 保护修饰符
class Person {
  protected name: string;
  constructor(name: string) { this.name = name; }
}

class Employee extends Person {
  private department: string;
  
  constructor(name: string, department: string) {
    super(name);
    this.department = department;
  }
  
  public getElevatorPitch() {
    return `Hello, my name is ${this.name} and I work in ${this.department}.`;
  }
}

let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
// console.log(howard.name); // 错误

参数属性

typescript
class Octopus {
  readonly numberOfLegs: number = 8;
  constructor(readonly name: string) { // 参数属性创建并初始化成员
  }
}

存取器

typescript
class Employee3 {
  private _fullName: string = "";
  
  get fullName(): string {
    return this._fullName;
  }
  
  set fullName(newName: string) {
    if (passcode && passcode == "secret passcode") {
      this._fullName = newName;
    } else {
      console.log("Error: Unauthorized update of employee!");
    }
  }
}

let employee = new Employee3();
employee.fullName = "Bob Smith";
if (employee.fullName) {
  console.log(employee.fullName);
}

静态属性

typescript
class Grid {
  static origin = {x: 0, y: 0};
  calculateDistanceFromOrigin(point: {x: number; y: number;}) {
    let xDist = (point.x - Grid.origin.x);
    let yDist = (point.y - Grid.origin.y);
    return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
  }
  constructor(public scale: number) { }
}

let grid1 = new Grid(1.0);  // 1x scale
let grid2 = new Grid(5.0);  // 5x scale

console.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));

抽象类

typescript
abstract class Animal3 {
  abstract makeSound(): void;
  move(): void {
    console.log("roaming the earth...");
  }
}

class Dog extends Animal3 {
  makeSound(): void {
    console.log("Woof! Woof!");
  }
}

// let a = new Animal3(); // 错误: 不能创建抽象类的实例
let d = new Dog(); // 正确

高级接口概念

函数接口

typescript
interface Counter {
  (start: number): string;
  interval: number;
  reset(): void;
}

function createCounter(): Counter {
  let counter = <Counter>function (start: number) { };
  counter.interval = 123;
  counter.reset = function () { };
  return counter;
}

接口继承类

typescript
class Control {
  private state: any;
}

interface SelectableControl extends Control {
  select(): void;
}

class Button extends Control implements SelectableControl {
  select() { }
}

class TextBox extends Control {
  select() { }
}

// 错误:Image 类不能实现 SelectableControl
// 因为它没有继承 Control
// class Image implements SelectableControl {
//   select() { }
// }

类与接口的实用模式

配置对象模式

typescript
interface Config {
  width?: number;
  height?: number;
  color?: string;
}

function createBox(config: Config): { width: number; height: number; color: string } {
  let newBox = { width: 0, height: 0, color: "white" };
  
  if (config.width) {
    newBox.width = config.width;
  }
  
  if (config.height) {
    newBox.height = config.height;
  }
  
  if (config.color) {
    newBox.color = config.color;
  }
  
  return newBox;
}

let myBox = createBox({ width: 100, color: "red" });

索引签名

typescript
interface StringArray {
  [index: number]: string;
}

interface NumberDictionary {
  [index: string]: number;
  length: number;    // 可以,length 是 number 类型
  name: string;      // 错误,类型不匹配
}

// 防止意外添加属性
interface SquareConfig {
  color?: string;
  width?: number;
  [propName: string]: any; // 允许添加其他属性
}

小结

接口和类是 TypeScript 面向对象编程的核心。接口定义契约,类实现具体功能。通过合理使用接口和类,可以创建结构清晰、类型安全的代码,提高代码的可维护性和可扩展性。