在 TypeScript 中,接口(interface) 和 类型别名(type) 都可以用来定义类型,但它们有一些关键区别。理解这些区别可以帮助你在不同场景下选择更合适的工具。
1. 基本定义
-
接口(interface):
-
用于定义对象的形状(即属性和方法)。
-
支持继承和扩展。
-
主要用于描述对象、类或函数的契约。
-
interface Person {
name: string;
age: number;
}
类型别名(type):
-
可以为任何类型创建别名,包括基本类型、联合类型、交叉类型等。
-
不支持继承,但可以通过交叉类型实现类似功能。
-
更灵活,适用于定义复杂类型。
type Person = {
name: string;
age: number;
};
2. 扩展性
-
接口:
-
支持通过
extends
关键字继承其他接口。 -
支持声明合并(同名接口会自动合并)。
-
interface Animal {
name: string;
}
interface Dog extends Animal {
bark(): void;
}
类型别名:
-
不支持继承,但可以通过交叉类型(
&
)实现类似功能。 -
不支持声明合并。
type Animal = {
name: string;
};
type Dog = Animal & {
bark(): void;
};
3. 声明合并
-
接口:
-
如果定义了多个同名接口,TypeScript 会自动合并它们。
-
适用于扩展第三方库的类型定义。
-
interface User {
name: string;
}
interface User {
age: number;
}
const user: User = {
name: "Alice",
age: 25,
};
类型别名:
-
不支持声明合并。如果定义多个同名类型别名,会报错。
type User = {
name: string;
};
type User = {
age: number;
}; // 报错:重复标识符 'User'
4. 适用场景
-
接口:
-
更适合定义对象的形状。
-
适合与类一起使用(通过
implements
实现接口)。 -
适合需要扩展或合并的场景。
-
interface Person {
name: string;
}
class Student implements Person {
name: string;
constructor(name: string) {
this.name = name;
}
}
类型别名:
-
更适合定义联合类型、交叉类型或复杂类型。
-
适合定义一次性使用的类型。
type ID = string | number;
type Coordinates = [number, number];
5. 函数类型
-
接口:
-
可以描述函数类型,但语法稍显冗长。
-
interface Add {
(a: number, b: number): number;
}
const add: Add = (a, b) => a + b;
- 类型别名:
-
描述函数类型更简洁。
-
type Add = (a: number, b: number) => number;
const add: Add = (a, b) => a + b;
6. 元组和联合类型
-
接口:
-
不支持直接定义元组或联合类型。
-
-
类型别名:
-
支持定义元组和联合类型。
-
type Point = [number, number];
type Result = "success" | "failure";
7. 实现类
-
接口:
-
类可以通过
implements
关键字实现接口。
-
interface Animal {
name: string;
speak(): void;
}
class Dog implements Animal {
name: string;
constructor(name: string) {
this.name = name;
}
speak() {
console.log("Woof!");
}
}
-
类型别名:
-
不能直接用于类的实现。
-
8. 性能
-
接口:
-
在大型项目中,接口的声明合并可能会导致性能问题(因为需要合并多个接口定义)。
-
-
类型别名:
-
性能更好,因为类型别名是静态的,不会发生合并。
-
总结对比
特性 | 接口(interface) | 类型别名(type) |
---|---|---|
定义对象形状 | 是 | 是 |
继承 | 支持(extends ) | 不支持(但可通过交叉类型实现) |
声明合并 | 支持 | 不支持 |
函数类型 | 支持(语法稍冗长) | 支持(语法简洁) |
联合类型 | 不支持 | 支持 |
元组 | 不支持 | 支持 |
实现类 | 支持(implements ) | 不支持 |
适用场景 | 对象、类、扩展第三方类型 | 联合类型、交叉类型、复杂类型 |
使用建议
-
如果需要定义对象的形状或与类一起使用,优先选择 接口。
-
如果需要定义联合类型、交叉类型或复杂类型,优先选择 类型别名。
-
如果需要扩展第三方库的类型定义,使用 接口 的声明合并功能。
根据具体场景选择合适的工具,可以使代码更加清晰和可维护。