在 TypeScript(TS)中,type 和 interface 都可以用来定义对象的结构,但它们有一些重要的差异以及独特的用法。了解它们各自的特点和使用场景有助于在项目中做出最佳选择。
TypeScript 中的 type
type 是一种类型别名,用于定义复杂类型的简写。它不仅可以用于对象类型,还可以用于其他类型(如联合类型、交叉类型、原始类型等)。
特点:
-
灵活性:
type可以表示几乎任何类型,包括基本类型、联合类型、交叉类型、函数类型等。
typescript 复制代码 type Primitive = string | number | boolean; // 联合类型 type Point = { x: number; y: number }; // 对象类型 type Complex = Point & { z: number }; // 交叉类型 -
无法重新声明:
- 一旦定义了
type,不能通过相同的名称再次扩展或修改。
typescript 复制代码 type User = { name: string }; // type User = { age: number }; // ❌ 报错:重复声明 - 一旦定义了
-
适合组合:
type更加擅长定义复杂类型,通过&和|进行组合。
typescript 复制代码 type A = { propA: string }; type B = { propB: number }; type AB = A & B; // { propA: string; propB: number }
TypeScript 中的 interface
interface 是专门用来定义对象的结构或类的约束的,更接近传统面向对象编程中的接口概念。
特点:
-
支持扩展:
interface可以通过继承的方式扩展已有的接口,或者直接扩展多个接口。
interface User { name: string; } interface Admin extends User { permissions: string[]; } -
可以重复声明:
- 在同一个作用域中,可以对同名的接口进行扩展或合并。
interface User { name: string; } interface User { age: number; } // 等效于:{ name: string; age: number } -
适合类的定义:
- 常用于类的类型约束,实现面向对象编程的接口语义。
interface Greeter { greet(): void; } class Hello implements Greeter { greet() { console.log("Hello"); } }
type 和 interface 的对比
| 特性 | type | interface |
|---|---|---|
| 用法范围 | 通用(对象、函数、联合、交叉、基本类型等) | 专注于定义对象和类的结构 |
| 扩展性 | 不支持重复声明;通过交叉类型扩展 | 支持重复声明;通过 extends 扩展 |
| 复杂类型 | 适合复杂类型,如联合类型、交叉类型等 | 仅适合定义对象和类结构 |
| 类的实现 | 不支持类的直接实现 | 可以用作类的接口约束,实现 OOP 语义 |
| 性能优化 | 不受重载机制优化 | 在合并声明时,TS 编译器更易优化 |
TypeScript 的 interface 与 Java 的 interface 对比
| 特性 | TypeScript 的 interface | Java 的 interface |
|---|---|---|
| 多继承 | 支持继承多个接口 | 支持继承多个接口 |
| 字段实现 | 只定义结构,不能实现具体逻辑 | 允许定义默认方法(Java 8+) |
| 运行时检查 | 仅用于编译时检查,运行时无影响 | 运行时存在,反映在 JVM 中 |
| 泛型支持 | 支持泛型 | 支持泛型 |
| 数据类型 | 可定义任意复杂类型(如联合、交叉类型) | 仅支持对象类型 |
选择建议
-
使用
interface:- 当你需要描述对象的结构,特别是类的约束时,优先使用
interface。 - 如果需要扩展或第三方库中有同名接口需要合并,用
interface。
- 当你需要描述对象的结构,特别是类的约束时,优先使用
-
使用
type:- 如果要定义非对象类型(如联合类型、交叉类型、函数类型),用
type。 - 如果你的类型定义较为复杂(如涉及多种组合),用
type。
- 如果要定义非对象类型(如联合类型、交叉类型、函数类型),用
综合示例
type ID = string | number; // 联合类型
interface User {
id: ID;
name: string;
}
type ExtendedUser = User & { age: number }; // 交叉类型扩展
const user: ExtendedUser = {
id: 1,
name: "Alice",
age: 30
};
interface Greeter {
greet(): void;
}
class Hello implements Greeter {
greet() {
console.log("Hello, world!");
}
}
4o