TypeScript interface 和 type 有什么区别?
在 TypeScript 中,interface(接口)和 type(类型别名)非常相似,在许多情况下可以互换使用。但在现代 TypeScript(尤其是 4.x/5.x 版本)中,它们的区别主要集中在扩展性、表达能力和语义上。
以下是详细的对比总结:
核心区别速览
| 特性 | Interface (接口) | Type (类型别名) |
|---|---|---|
| 定义对象/函数 | ✅ 支持 | ✅ 支持 |
| 声明合并 (Declaration Merging) | ✅ 支持 (自动合并) | ❌ 不支持 (报错重复定义) |
| 联合类型 (Union Types) | ❌ 不支持 | ✅ 支持 (A | B) |
| 基本类型别名 | ❌ 不支持 | ✅ 支持 (type Name = string) |
| 元组 (Tuple) | ❌ 语法繁琐 | ✅ 支持 ([string, number]) |
| 扩展方式 | 使用 extends 关键字 |
使用 & (交叉类型) |
| 映射类型 (Mapped Types) | ❌ 不支持 | ✅ 支持 (in keyof) |
| 主要用途 | 定义对象结构、类契约、库的扩展 | 定义联合类型、工具类型、复杂组合 |
详细区别解析
1. 声明合并 (Declaration Merging) —— 最重要的区别
这是 interface 独有的特性。如果你定义了两个同名的 interface,TypeScript 会自动把它们合并成一个。
Interface:
typescriptinterface User { name: string; } interface User { age: number; } // 结果:User 包含 name 和 age const user: User = { name: "Alice", age: 18 };应用场景: 这对于扩展第三方库(如向
Window对象添加属性)非常重要。Type:
typescripttype User = { name: string; }; // 报错:Duplicate identifier 'User'. type User = { age: number; };
2. 类型表达能力 (Type Capabilities)
type 的表达能力更强,它可以定义非对象类型。
- 基本类型别名:typescript
type ID = string; // interface 做不到 - 联合类型 (Union Types):typescript
type Status = "success" | "error" | "loading"; // interface 做不到 - 元组 (Tuples):typescript
type Point = [number, number]; // interface 做不到这么简洁
3. 扩展方式 (Extensibility)
两者都可以扩展,但语法不同。
Interface 使用
extends(更具面向对象语义):typescriptinterface Animal { name: string; } interface Bear extends Animal { honey: boolean; }Type 使用
&(交叉类型):typescripttype Animal = { name: string; }; type Bear = Animal & { honey: boolean; };注意:Interface 也可以
extends一个 Type(只要该 Type 是对象结构),Type 也可以&一个 Interface。
4. 映射类型 (Mapped Types)
如果你需要遍历键来生成新类型,必须使用 type。
typescript
type Keys = "firstName" | "lastName";
type DuplicateMap = {
[K in Keys]: string;
};
// interface 无法直接使用 in keyof 语法
5. 错误提示与性能 (微小差异)
- Interface: 创建了一个新的名字。在报错时,通常会直接显示接口名称(如
User)。 - Type: 只是一个别名。在某些复杂的交叉类型或联合类型中,报错时可能会把具体的结构展开显示,而不是显示别名(不过新版 TS 在这方面优化了很多)。
- 性能: 官方曾提到
interface的类型检查性能略优于交叉类型 (type的&),因为接口可以缓存属性关系,但这通常只在巨型项目中才有感知。
最佳实践:该用哪个?
虽然没有绝对的标准,但社区和官方通常建议如下:
优先使用
interface定义对象结构:- 如果你是在定义一个对象(Object)的形状。
- 如果你是在编写库(Library)或公共 API,因为使用者可能需要通过声明合并来扩展你的接口。
- 如果你在使用面向对象编程(Class
implements)。
在以下情况使用
type:- 定义联合类型(如
type ID = string | number)。 - 定义基本类型的别名。
- 定义元组。
- 使用高级类型功能(如映射类型、条件类型、提取类型等工具类型)。
- 定义 React 组件的 Props 时,现在社区中
type和interface混用,但使用type略多一些,因为它处理联合类型更方便。
- 定义联合类型(如
简单总结口诀:
"对象结构用 Interface,复杂组合与别名用 Type,库的公开类型必须用 Interface。"