TypeScript 类型定义:interface 与 type alias
TypeScript 提供了两种主要的方式来定义类型:interface(接口)和 type alias(类型别名)。虽然两者在许多情况下可以互换使用,但在处理复杂的类型结构时,它们各有独特的行为。理解这些差异能帮助你写出更健壮、更易维护的代码。
1. 基础对象定义
对于定义简单的对象结构,两者的语法非常相似,功能也几乎一致。
定义一个包含 name 和 age 的用户对象。
使用 interface:
interface User {
name: string;
age: number;
}
使用 type:
type User = {
name: string;
age: number;
};
在这两种情况下,声明一个变量并赋值的效果完全相同。
const user1: User = { name: "Alice", age: 25 };
2. 类型别名的独有能力
type alias 的能力范围比 interface 更广,它可以用于定义原始类型、联合类型、元组等非对象结构。
2.1 定义联合类型
当你需要表示一个值可以是多种类型之一时,使用 type。
定义一个 ID 类型,它可以是字符串或数字。
type ID = string | number;
const userId: ID = "abc-123";
const productId: ID = 98765;
2.2 定义元组类型
当你需要表示一个已知长度和类型的数组时,使用 type。
定义一个坐标类型,包含两个数字。
type Coordinate = [number, number];
const location: Coordinate = [10.5, 20.3];
2.3 映射类型
在构建工具类型时,通常使用 type 结合 keyof。
创建一个将所有属性变为可选的类型工具。
type PartialUser = {
[K in keyof User]?: User[K];
};
3. 接口的独有能力
interface 最核心的特性是“声明合并”。这意味着如果定义了多个同名接口,TypeScript 会自动将它们合并为一个接口。
3.1 声明合并
这在扩展第三方库的类型时非常有用。
定义一个 Window 接口包含 title 属性。
interface Window {
title: string;
}
再次定义一个 Window 接口包含 version 属性。
interface Window {
version: string;
}
此时,Window 类型将同时包含 title 和 version。
const windowProps: Window = {
title: "My App",
version: "1.0.0"
};
如果尝试使用 type 进行同名定义,TypeScript 会抛出错误:Duplicate identifier 'Window'。
4. 继承与扩展
两者都支持继承,但语法略有不同。
4.1 Interface 继承 Interface
使用 extends 关键字。
interface Animal {
name: string;
}
interface Bear extends Animal {
honey: boolean;
}
4.2 Type 继承 Type
使用交叉类型 &。
type Animal = {
name: string;
};
type Bear = Animal & {
honey: boolean;
};
4.3 Interface 继承 Type
接口可以继承类型别名。
type Animal = {
name: string;
};
interface Bear extends Animal {
honey: boolean;
}
4.4 Type 继承 Interface
类型别名也可以继承接口,同样使用交叉类型 &。
interface Animal {
name: string;
}
type Bear = Animal & {
honey: boolean;
};
5. 决策指南
在实际开发中,选择哪一个主要取决于你的具体需求。下表总结了关键区别与选择依据。
| 特性 | Interface | Type Alias |
|---|---|---|
| 定义对象 | 支持 | 支持 |
定义联合类型 (A \| B) |
不支持 | 支持 |
定义元组 ([A, B]) |
不支持 | 支持 |
| 声明合并 (同名合并) | 支持 | 不支持 |
| 扩展方式 | extends |
交叉类型 & |
| 适用场景 | 定义对象模型、库的 API 定义 | 定义联合类型、工具类型、复杂类型组合 |
6. 快速选择流程
为了在编码时快速做出判断,可以参考以下决策流程。
解读流程图:
- 检查数据类型。如果是基本类型、联合类型(
string | number)或元组,直接使用type。 - 如果是对象或函数,判断是否需要“声明合并”。如果你需要多次定义同名类型来扩展它(例如给
window对象挂载属性),必须使用interface。 - 如果不需要合并,判断是否涉及复杂的映射类型(如
Pick<T, K>、泛型工具)。通常这些场景下type更灵活。 - 如果以上都不涉及,遵循团队或项目的统一代码风格。在纯面向对象编程中,
interface是传统选择;在函数式编程或 React 组件 Props 定义中,type非常流行。

暂无评论,快来抢沙发吧!