接口(Interface)是 TypeScript 中用于定义对象结构的强大特性。它用于描述对象的形状(Shape),提供代码的类型安全性和可维护性。本指南将全面介绍 TypeScript 接口的概念、使用方式、继承、可选属性、只读属性等内容。
目录
1. 什么是接口?
接口(interface
)是一种用于描述对象类型的工具,定义了对象必须包含的属性和方法,但不提供具体实现。它主要用于确保代码结构的一致性。
interface Person {
name: string;
age: number;
}
在上述代码中,Person
接口描述了一个对象应有的 name
和 age
属性。
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 官方文档:Interfaces
- MDN 文档:TypeScript 类型系统
- TypeScript 深入指南:TypeScript Deep Dive
接口是 TypeScript 代码组织和类型安全的核心概念。掌握接口的使用,可以让你的 TypeScript 代码更加健壮、易维护,并提高开发效率。
发表回复