第三节 类型系统进阶-接口(interface)与类型别名(type)的区别
一、本质区别概览
特性 | 接口(interface) | 类型别名(type) |
---|---|---|
定义对象结构 | ✅ 原生支持(核心用途) | ✅ 支持 |
扩展性 | ✅ 通过 extends 继承 | ✅ 通过交叉类型 & 组合 |
声明合并 | ✅ 同名接口自动合并 | ❌ 禁止重复定义 |
支持类型范围 | ❌ 仅限对象、函数、类 | ✅ 基本类型、联合、元组、映射类型等任意类型 |
泛型 | ✅ 支持 | ✅ 支持(更灵活,可结合条件类型等高级特性) |
类实现 | ✅ 类可通过 implements 实现接口 | ❌ 无法被类实现 |
二、核心差异详解
1. 声明合并(Declaration Merging)
- 接口:同名接口自动合并属性,适用于扩展第三方库类型或增量定义。
interface User { name: string; } interface User { age: number; } // 合并为 { name: string; age: number; }
- 类型别名:重复定义会报错,强制单一职责。
type User = { name: string; }; type User = { age: number; }; // Error: Duplicate identifier 'User'
2. 扩展机制
- 接口:通过
extends
实现继承,符合面向对象设计。interface Animal { name: string; } interface Dog extends Animal { breed: string; }
- 类型别名:通过交叉类型
&
组合,更函数式风格。type Animal = { name: string; }; type Dog = Animal & { breed: string; };
3. 适用场景差异
场景 | 推荐方案 | 原因 |
---|---|---|
定义对象结构 | 优先接口 | 更直观,支持声明合并和类实现 |
联合类型/元组 | 必须类型别名 | 接口无法直接定义 `string |
函数类型 | 两者均可 | 接口语法:{ (arg: T): U } ,类型别名:(arg: T) => U |
映射类型/条件类型 | 必须类型别名 | 接口不支持高级类型操作(如 Partial<T> 、keyof ) |
4. 类型兼容性
- 对象结构:两者在结构类型系统中行为一致(鸭子类型)。
interface A { x: number; } type B = { x: number; }; let a: A = { x: 1 }; let b: B = a; // ✅ 兼容
- 扩展冲突处理:
- 接口继承时同名属性类型必须一致,否则报错:
interface A { prop: number; } interface B { prop: string; } interface C extends A, B {} // Error: 类型冲突
- 类型别名通过交叉类型合并时,同名属性会合并为
never
:type AB = { prop: number; } & { prop: string; }; // prop 类型为 never(实际无法赋值)
- 接口继承时同名属性类型必须一致,否则报错:
三、开发实践建议
-
默认选择接口:
- 面向对象场景(如类实现、API 契约)优先使用接口。
- 利用声明合并扩展第三方类型(如为
Window
添加自定义属性)。
-
以下场景使用类型别名:
- 定义联合类型(
type Status = "success" | "error"
)。 - 创建元组(
type Point = [number, number]
)。 - 复杂类型操作(如映射类型、条件类型):
type Partial<T> = { [P in keyof T]?: T[P] };
- 定义联合类型(
-
避免混用陷阱:
- 接口扩展类型别名:✅ 支持:
type Animal = { name: string; }; interface Dog extends Animal { breed: string; }
- 类型别名扩展接口:✅ 通过
&
实现:interface Animal { name: string; } type Dog = Animal & { breed: string; };
- 接口扩展类型别名:✅ 支持:
四、总结对比表
维度 | 接口(interface) | 类型别名(type) |
---|---|---|
核心定位 | 对象结构契约 | 类型别名(任意类型) |
扩展性 | extends 继承 | 交叉类型 & 组合 |
声明合并 | ✅ 自动合并 | ❌ 禁止重复 |
高级类型支持 | ❌ 不支持联合、映射等 | ✅ 全面支持 |
类实现 | ✅ implements 支持 | ❌ 不可用 |
适用哲学 | 面向对象设计 | 函数式/类型编程 |
💡 决策指南:
- 大型项目或需要扩展性 → 接口(如组件 Props、状态管理);
- 复杂类型操作或一次性类型 → 类型别名(如工具类型、联合类型)。
两者互补使用可最大化 TypeScript 类型系统的威力。