TypeScript 核心概念:type vs interface,如何明智选择?
在 TypeScript 中,type 和 interface 是定义类型约束的两大基石。它们功能高度重叠,常让开发者困惑:究竟该用哪个?理解它们的细微差异和最佳适用场景至关重要。
核心相似点:定义形状
两者都能描述对象结构:
interface PersonInterface {
name: string;
age: number;
}
type PersonType = {
name: string;
age: number;
};
关键差异:能力与意图
扩展性 (
extendsvs&):interface使用extends继承:interface Employee extends PersonInterface { jobTitle: string; }type使用交叉类型&:type Employee = PersonType & { jobTitle: string };
声明合并 (Declaration Merging):
interface的独有能力:同名的interface声明会自动合并。interface User { name: string; } interface User { age: number; } // 最终 User 是 { name: string; age: number; }type不允许重复定义。同名type会报错。
表达能力范围:
type更灵活,能定义任何类型:- 联合类型:
type ID = string | number; - 元组类型:
type Point = [number, number]; - 映射类型:
type Readonly<T> = { readonly [K in keyof T]: T[K]; } - 条件类型:
type NonNullable<T> = T extends null | undefined ? never : T;
- 联合类型:
interface主要描述对象形状(也可扩展函数、索引签名等)。
实现 (
implements):- 类可以实现 (
implements) 一个interface或一个表示对象形状的type:class Student implements PersonType { ... } // 或 PersonInterface
- 类可以实现 (
最佳实践:何时选择?
优先使用
interface当:- 定义对象结构(尤其是公共 API 契约,如库的导出)。
- 需要利用声明合并(扩展第三方库类型、环境声明)。
- 需要清晰的面向对象继承 (
extends)。
优先使用
type当:- 定义非对象类型(联合、元组、函数类型、复杂映射/条件类型)。
- 需要组合多个类型(
&操作符非常直接)。 - 定义的类型不需要声明合并,且更倾向于单一精确来源。
总结表
| 特性 | interface |
type |
|---|---|---|
| 定义对象形状 | ✅ 主要用途 | ✅ |
| 扩展/继承 | extends |
交叉类型 & |
| 声明合并 | ✅ (核心特性) | ❌ (禁止重复) |
| 定义联合/元组 | ❌ (有限制) | ✅ |
| 映射/条件类型 | ❌ | ✅ (强大灵活) |
类 implements |
✅ | ✅ (对象形状的 type) |
核心理念: 两者都是 TS 类型系统的支柱。interface 强调可扩展的契约,type 提供灵活的类型操作。根据具体场景和团队约定选择,保持一致性是关键!理解差异,扬长避短。