TypeScript 接口:interface 与 type 的区别
在 TypeScript 项目中,定义数据结构时常常面临一个选择:使用 interface 还是 type。虽然两者在许多情况下表现相似,但在底层机制、扩展能力和适用场景上存在显著差异。掌握这些区别,有助于编写更规范、更易维护的代码。
1. 定义基础对象结构
对于最普通的对象定义,两者在语法和最终生成的类型检查上几乎完全一致。
执行以下代码分别定义一个用户对象:
// 使用 interface 定义
interface UserInterface {
id: number;
name: string;
}
// 使用 type 定义
type UserType = {
id: number;
name: string;
};
在使用层面,这两种定义方式没有任何区别。你可以互换地使用 UserInterface 或 UserType 来声明变量。在此场景下,选择哪一种主要取决于团队或项目的代码风格偏好。
2. 处理联合类型、交叉类型与基本类型别名
这是 type 关键字最核心的优势领域。interface 只能用于定义对象的结构,而 type 可以给任意类型起别名,包括基本类型、联合类型、元组等。
使用 type 定义一个联合类型,表示 ID 可以是数字或字符串:
type ID = number | string;
// 尝试用 interface 定义会报错
// interface ID = number | string; // Error
使用 type 定义一个元组类型,精确规定数组元素的顺序和类型:
type Coordinate = [number, number];
const point: Coordinate = [100, 200];
记住:当你需要处理非对象类型(如 string | number)、工具类型(如 Partial)或复杂的类型组合时,必须 使用 type。
3. 继承与扩展的方式
虽然两者都可以实现类型的扩展,但语法和底层逻辑不同。
使用 extends 关键字让 interface 继承另一个 interface:
interface Animal {
name: string;
}
interface Bear extends Animal {
honey: boolean;
}
使用 交叉类型(&)扩展 type:
type Animal = {
name: string;
};
type Bear = Animal & {
honey: boolean;
};
这里有一个关键的互通性:interface 可以继承 type(只要该 type 是对象类型),type 也可以交叉 interface。
注意,当处理同名属性冲突时,两者的行为不同:
interface继承时,如果属性类型不兼容,会直接报错。type交叉时,属性类型会进行交叉运算(对于基础类型,通常会导致never类型,因为一个值不可能既是 string 又是 number)。
4. 声明合并
这是 interface 独有的特性,也是区分使用场景的重要依据。同名 interface 会自动合并为一个定义,而同名 type 会直接报错。
定义两个同名的 interface:
interface Window {
title: string;
}
interface Window {
status: string;
}
TypeScript 会自动将其合并为:
interface Window {
title: string;
status: string;
}
尝试对 type 做同样的操作:
type Window = {
title: string;
};
// Error: Duplicate identifier 'Window'
type Window = {
status: string;
};
应用场景:当你需要扩展第三方库或全局对象(如 Window、Document 或全局 CSS 模块)的类型定义时,必须 使用 interface 进行声明合并。
5. 映射类型的性能表现
在处理复杂的映射类型(如使用 Record、Pick、Omit 等工具类型)时,type 通常是首选。
定义一个复杂的映射类型:
type Keys = 'name' | 'age';
type Person = {
[K in Keys]: string;
};
虽然 interface 可以通过 Record 工具间接实现类似功能,但在处理动态键值对或复杂的类型体操时,type 的语法更加直观且功能更强大。大型类型计算库(如 utility-types)通常都基于 type 构建,因为 type 能够构建更复杂的类型图。
6. 决策流程图
为了在实际开发中快速做出判断,请遵循以下逻辑:
7. 核心差异对比表
下表总结了两者在关键维度上的区别:
| 特性 | interface | type |
|---|---|---|
| 定义对象 | 支持 | 支持 |
| 定义联合/元组 | 不支持 | 支持 |
| 基本类型别名 | 不支持 | 支持 |
| 继承方式 | extends |
交叉类型 & |
| 声明合并 | 支持 | 不支持 |
| 计算属性/映射 | 较弱 | 强大 |

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