一、前言
在 TypeScript 中,接口(Interface) 是一种非常重要的工具,它允许我们为对象的形状(shape)设定结构规范,从而提高代码的可维护性、可读性和健壮性。
本文将带你从零开始学习 TypeScript 接口,包括:
✅ 接口的基本语法
✅ 属性修饰符(可选、只读)
✅ 方法定义与函数类型接口
✅ 接口继承与实现
✅ 数组类型与索引签名
✅ 类对接口的实现
✅ 接口 vs 类型别名(interface vs type)
✅ 实际开发中的应用案例
并通过完整的代码示例帮助你快速上手并掌握接口的强大功能。
二、什么是接口?
✅ 定义:
接口是一种定义对象结构的方式,它不包含具体的实现逻辑,只描述一个对象应该具备哪些属性和方法。
⚠️ 接口是 TypeScript 提供的一种静态类型检查机制,不会影响最终的 JavaScript 输出。
三、接口的基本用法
✅ 示例:定义一个简单的接口
interface Person {
name: string;
age: number;
sayHello(): void;
}
const user: Person = {
name: "Alice",
age: 25,
sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
};
user.sayHello(); // 输出:Hello, my name is Alice
四、接口中的属性修饰符
✅ 1. 可选属性(Optional Properties)
通过 ? 标记某个属性为可选。
interface User {
id: number;
name: string;
email?: string; // 可选属性
}
✅ 2. 只读属性(Readonly Properties)
使用 readonly 关键字限制属性只能在初始化时赋值。
interface Product {
readonly id: number;
name: string;
}
const product: Product = { id: 1, name: "Laptop" };
// product.id = 2; ❌ 报错:id 是只读属性
五、函数类型接口
接口不仅可以描述对象,还可以用于定义函数的参数和返回值类型。
✅ 示例:定义函数接口
interface SumFunction {
(a: number, b: number): number;
}
const add: SumFunction = (x, y) => x + y;
console.log(add(3, 5)); // 输出:8
六、数组类型接口与索引签名
✅ 1. 数组类型接口
interface StringArray {
[index: number]: string;
}
const fruits: StringArray = ["Apple", "Banana"];
console.log(fruits[0]); // Apple
✅ 2. 索引签名(Index Signature)
接口中也可以定义字符串索引签名,适用于动态键的对象。
interface Dictionary {
[key: string]: number;
}
const scores: Dictionary = {
math: 90,
english: 85
};
七、接口继承(Extends)
一个接口可以通过 extends 继承另一个或多个接口。
✅ 单继承示例:
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
const dog: Dog = {
name: "Buddy",
breed: "Golden Retriever"
};
✅ 多继承示例:
interface Identifiable {
id: number;
}
interface Timestamped {
createdAt: Date;
}
interface LogEntry extends Identifiable, Timestamped {
message: string;
}
const entry: LogEntry = {
id: 1,
createdAt: new Date(),
message: "System started"
};
八、类实现接口(Implements)
类可以使用 implements 来实现一个或多个接口,并必须提供接口中定义的所有属性和方法。
✅ 示例:类实现接口
interface Logger {
log(message: string): void;
}
class ConsoleLogger implements Logger {
log(message: string): void {
console.log(`[LOG] ${message}`);
}
}
const logger = new ConsoleLogger();
logger.log("Application started"); // 输出:[LOG] Application started
九、接口 vs 类型别名(Interface vs Type)
| 特性 | Interface | Type |
|---|---|---|
| 是否支持合并声明 | ✅ 是(自动合并) | ❌ 否 |
| 是否支持继承 | ✅ 是(extends) | ✅ 是(交叉类型) |
| 是否支持类实现 | ✅ 是 | ✅ 是 |
| 是否适合大型项目 | ✅ 更推荐 | ✅ 也适用 |
| 是否可以是联合类型 | ❌ 否 | ✅ 是 |
✅ 示例对比:
type Point = {
x: number;
y: number;
};
interface Point {
x: number;
y: number;
}
两者在大多数情况下等价,但在大型项目中建议优先使用 interface,因为它支持声明合并和更清晰的面向对象语义。
十、实际开发中的应用场景
✅ 场景1:定义 API 响应格式
interface ApiResponse<T> {
status: "success" | "error";
data?: T;
error?: string;
}
function fetchUser(): ApiResponse<{ id: number; name: string }> {
return {
status: "success",
data: { id: 1, name: "Alice" }
};
}
✅ 场景2:组件 props 类型定义(React)
interface ButtonProps {
label: string;
onClick?: () => void;
disabled?: boolean;
}
function Button({ label, onClick, disabled }: ButtonProps) {
return (
<button onClick={onClick} disabled={disabled}>
{label}
</button>
);
}
十一、注意事项与最佳实践
| 场景 | 建议 |
|---|---|
是否推荐使用 readonly | ✅ 推荐用于防止意外修改数据 |
| 是否推荐使用可选属性 | ✅ 推荐用于部分字段非必填的场景 |
| 接口命名规范 | ✅ 使用大驼峰命名法(如 UserProfile) |
| 接口合并 | ✅ 在模块化项目中合理利用接口合并特性 |
| 接口嵌套 | ✅ 避免过度嵌套,保持简洁易读 |
十二、总结对比表:TypeScript 接口常用特性一览
| 特性 | 示例 | 说明 |
|---|---|---|
| 基础接口定义 | interface Person { name: string } | 描述对象结构 |
| 可选属性 | email?: string | 属性可有可无 |
| 只读属性 | readonly id: number | 初始化后不可修改 |
| 函数类型接口 | (a: number): number | 定义函数参数与返回值 |
| 数组接口 | [index: number]: string | 描述数组结构 |
| 索引签名 | [key: string]: any | 支持任意键的对象 |
| 接口继承 | interface Child extends Parent | 实现接口复用 |
| 类实现接口 | class A implements B | 强制实现特定行为 |
| 接口合并 | 多个同名 interface 自动合并 | 模块化开发利器 |
| 接口 vs 类型别名 | interface / type | 推荐 interface 用于 OOP |
十三、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!