接口(Interface)是 TypeScript 中用于定义对象结构的强大特性。它用于描述对象的形状(Shape),提供代码的类型安全性和可维护性。本指南将全面介绍 TypeScript 接口的概念、使用方式、继承、可选属性、只读属性等内容。


目录

  1. 什么是接口?
  2. 接口的基本用法
  3. 可选属性与只读属性
  4. 函数类型的接口
  5. 类实现接口
  6. 接口的继承
  7. 混合类型的接口
  8. 接口 vs. 类型别名
  9. 最佳实践
  10. 参考资料

1. 什么是接口?

接口(interface)是一种用于描述对象类型的工具,定义了对象必须包含的属性和方法,但不提供具体实现。它主要用于确保代码结构的一致性。

interface Person {
    name: string;
    age: number;
}

在上述代码中,Person 接口描述了一个对象应有的 nameage 属性。


2. 接口的基本用法

接口可以用于定义对象的结构,并用 : 进行类型注解:

interface User {
    username: string;
    email: string;
}

const user: User = {
    username: "JohnDoe",
    email: "johndoe@example.com"
};

注意:

  • 对象必须符合接口结构,否则 TypeScript 会报错。
  • 多余的属性会被检查,如果对象包含未在接口中声明的属性,可能会导致错误(除非使用索引签名)。

3. 可选属性与只读属性

可选属性(? 标记)

可以使用 ? 来定义可选属性,表示该属性可以省略:

interface Car {
    brand: string;
    model?: string; // 可选属性
}

const car1: Car = { brand: "Toyota" }; // ✅ 合法
const car2: Car = { brand: "Ford", model: "Mustang" }; // ✅ 合法


只读属性(readonly 标记)

使用 readonly 关键字定义只读属性,防止被修改:

interface Config {
    readonly apiKey: string;
}

const config: Config = { apiKey: "123456" };
// config.apiKey = "newKey"; // ❌ 报错:只读属性不能修改


4. 函数类型的接口

接口也可以定义函数类型:

interface MathOperation {
    (x: number, y: number): number;
}

const add: MathOperation = (a, b) => a + b;
console.log(add(5, 3)); // 输出 8

这里 MathOperation 描述了一个接受两个 number 类型参数并返回 number 的函数。


5. 类实现接口

接口可以用 implements 关键字约束类的结构:

interface Animal {
    name: string;
    makeSound(): void;
}

class Dog implements Animal {
    name: string;

    constructor(name: string) {
        this.name = name;
    }

    makeSound() {
        console.log("Woof!");
    }
}

const myDog = new Dog("Buddy");
myDog.makeSound(); // 输出 "Woof!"

注意:

  • Dog 类必须实现 Animal 接口中定义的所有属性和方法,否则会报错。
  • 接口不能用于创建实例,它只是类型定义。

6. 接口的继承

接口支持继承(extends),可以扩展已有接口:

interface Person {
    name: string;
    age: number;
}

interface Employee extends Person {
    employeeId: number;
}

const emp: Employee = {
    name: "Alice",
    age: 30,
    employeeId: 12345
};

一个接口可以继承多个接口

interface CanFly {
    fly(): void;
}

interface CanSwim {
    swim(): void;
}

interface Bird extends CanFly, CanSwim {
    name: string;
}

const duck: Bird = {
    name: "Duck",
    fly: () => console.log("Flying"),
    swim: () => console.log("Swimming")
};


7. 混合类型的接口

接口可以同时包含属性方法

interface Counter {
    value: number;
    increment(): void;
}

const counter: Counter = {
    value: 0,
    increment() {
        this.value++;
    }
};

counter.increment();
console.log(counter.value); // 输出 1


8. 接口 vs. 类型别名

在 TypeScript 中,接口(Interface)类型别名(Type Alias) 都可以用于定义对象结构,但它们有一些关键区别:

特性接口(Interface)类型别名(Type Alias)
语法interface Person {}type Person = {}
扩展extends 继承其他接口& 交叉类型合并
可重用性可以合并定义不能合并定义
适用场景主要用于对象适用于联合类型、交叉类型、基本类型

一般来说:

  • 对象类型推荐使用接口(更直观,支持扩展)。
  • 复杂类型组合推荐使用类型别名(联合类型、交叉类型)。

9. 最佳实践

优先使用接口来描述对象结构,除非必须使用类型别名。
利用可选属性减少代码冗余,避免 undefined 赋值错误。
使用 readonly 保护不可变数据,确保对象不会意外被修改。
合理使用 extends 继承接口,保持代码模块化和可复用性。


10. 参考资料


接口是 TypeScript 代码组织和类型安全的核心概念。掌握接口的使用,可以让你的 TypeScript 代码更加健壮、易维护,并提高开发效率。