在 TypeScript 中,type
(类型别名)和 interface
(接口)都可以用来描述类型结构,但它们在功能、使用场景和行为上存在一些关键区别。理解这些区别有助于更合理地选择使用方式。
一、核心区别对比
特性 | interface |
type |
---|---|---|
基本用途 | 主要用于定义对象 / 函数的结构("形状") | 可定义任意类型(对象、基本类型、联合类型等) |
扩展方式 | 通过 extends 关键字扩展 |
通过交叉类型 & 扩展 |
合并声明 | 支持同名声明自动合并 | 不支持,同名会报错 |
类型范围 | 仅能描述对象 / 函数类型 | 可描述任意类型(包括基本类型、联合类型等) |
实现(implements ) |
类可以 implements 接口 |
类可以 implements 非联合类型的类型别名 |
映射类型 | 不支持直接定义映射类型 | 支持定义映射类型 |
二、详细区别解析
1. 定义的类型范围不同
interface
只能定义对象类型或函数类型 ,无法定义基本类型(如string
、number
)、联合类型、元组等。type
可以定义任意类型,包括基本类型别名、联合类型、交叉类型、元组等。
ts
// type 可以定义基本类型别名
type Age = number;
// type 可以定义联合类型
type Status = "active" | "inactive" | "pending";
// type 可以定义元组
type Point = [number, number];
// interface 只能定义对象/函数类型(以下正确)
interface User {
name: string;
age: number;
}
interface AddFn {
(a: number, b: number): number;
}
// interface 不能定义基本类型(以下错误)
interface MyString = string; // 报错:'interface' 声明只能用于声明对象类型或接口类型
2. 扩展方式不同
interface
通过extends
关键字扩展(更符合面向对象的继承语义)。type
通过交叉类型&
扩展(将多个类型合并为一个)。
ts
// interface 扩展
interface Animal {
name: string;
}
// 扩展 Animal 接口
interface Dog extends Animal {
bark(): void;
}
const dog: Dog = {
name: "Buddy",
bark: () => console.log("Woof!"),
};
// type 扩展(交叉类型)
type AnimalType = {
name: string;
};
// 交叉合并 AnimalType 和 新类型
type DogType = AnimalType & {
bark(): void;
};
const dog2: DogType = {
name: "Max",
bark: () => console.log("Woof!"),
};
3. 合并声明(Declaration Merging)
interface
支持同名声明自动合并(常用于扩展第三方库的类型定义)。type
不支持同名声明,重复定义会报错。
ts
// interface 同名合并
interface User {
name: string;
}
// 再次声明 User 接口,会自动合并
interface User {
age: number;
}
// 合并后:{ name: string; age: number }
const user: User = {
name: "Alice",
age: 20,
};
// type 同名会报错
type UserType = {
name: string;
};
type UserType = { // 报错:标识符"UserType"重复
age: number;
};
4. 与类的实现(implements
)
- 类可以通过
implements
实现interface
或非联合类型的type
。 - 类不能实现联合类型的
type
(因为联合类型包含多种可能结构,类无法同时满足)。
ts
interface Shape {
area(): number;
}
// 类实现 interface(正确)
class Circle implements Shape {
radius: number;
area() {
return Math.PI * this.radius **2;
}
}
type ShapeType = {
area(): number;
};
// 类实现非联合 type(正确)
class Square implements ShapeType {
side: number;
area() {
return this.side** 2;
}
}
// 联合类型的 type
type UnionShape = { area(): number } | { volume(): number };
// 类无法实现联合类型(报错)
class Cube implements UnionShape { // 报错:Cube 类型不能赋值给 UnionShape 类型
side: number;
volume() {
return this.side **3;
}
}
5. 映射类型支持
type
可以结合 in
关键字定义映射类型 (通过遍历联合类型生成新类型),而 interface
不支持。
typescript
// 定义一个联合类型
type Keys = "name" | "age";
// type 定义映射类型(将 Keys 中的每个键转为可选属性)
type Optional<T> = {
[K in keyof T]?: T[K];
};
type User = {
name: string;
age: number;
};
type OptionalUser = Optional<User>; // { name?: string; age?: number }
// interface 无法定义映射类型(以下错误)
interface OptionalInterface<T> {
[K in keyof T]?: T[K]; // 报错:接口成员不能包含"in"表达式
}
三、使用建议
-
优先用
interface
的场景:- 定义对象、函数的结构(明确 "形状")。
- 需要通过
extends
扩展或合并声明(如扩展第三方库类型)。 - 希望代码更符合面向对象的继承语义。
-
优先用
type
的场景:- 定义基本类型别名、联合类型、元组、交叉类型。
- 需要定义映射类型。
- 不需要合并声明,且类型逻辑更复杂(如组合多种类型)。
总结:interface
更侧重 "结构契约" 和扩展性,type
更侧重 "类型组合" 和灵活性。实际开发中可根据具体需求选择,两者并非互斥,有时也会结合使用(如 type
定义联合类型,interface
扩展它)。