- Published on
TypeScript type 和 interface区别
- Authors

- 作者
- kai
目录

TypeScript中type和interface的区别
基本定义
interface
用于定义对象的结构,描述对象应该具有的属性和方法。
interface User {
name: string;
age: number;
email?: string; // 可选属性
}
type
是类型别名,可以为任何类型创建一个新的名称。
type User = {
name: string;
age: number;
email?: string; // 可选属性
}
主要区别
1. 扩展性
interface支持扩展,可以通过继承来扩展其他接口:
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
// 也可以继承多个接口
interface Cat extends Animal {
color: string;
}
interface Robot {
model: string;
}
interface RoboDog extends Dog, Robot {
batteryLevel: number;
}
type可以通过交叉类型来实现类似的效果:
type Animal = {
name: string;
}
type Dog = Animal & {
breed: string;
}
// 也可以组合多个类型
type Robot = {
model: string;
}
type RoboDog = Dog & Robot & {
batteryLevel: number;
}
2. 声明合并
interface支持声明合并,即可以多次定义同一个接口,TypeScript会自动合并它们:
interface Window {
title: string;
}
interface Window {
ts: TypeScriptAPI;
}
// 最终Window接口包含title和ts两个属性
type不支持声明合并,重复定义会报错:
type Window = {
title: string;
}
// 错误:标识符“Window”重复
type Window = {
ts: TypeScriptAPI;
}
3. 类实现
类可以实现interface:
interface Point {
x: number;
y: number;
}
class MyPoint implements Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
类也可以实现type(只要义的是对象类型):
type Point = {
x: number;
y: number;
}
class MyPoint implements Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
4. 类型组合能力
type更灵活,可以用于定义各种类型,包括原始类型、联合类型、元组等:
// 基本类型别名
type Name = string;
// 联合类型
type Status = "pending" | "fulfilled" | "rejected";
// 元组
type Point = [number, number];
// 函数类型
type EventHandler = (event: Event) => void;
// 类型映射
type PartialUser = Partial<User>;
interface主要用于定义对象结构:
// 错误:interface不能用于定义基本类型
// interface Name = string;
// interface不能直接定义联合类型
// interface Status = "pending" | "fulfilled" | "rejected";
5. 循环引用
interface支持循环引用:
interface TreeNode {
value: string;
left?: TreeNode;
right?: TreeNode;
}
type在某些情况下可能不支持循环引用:
// 可能会报错
type TreeNode = {
value: string;
left?: TreeNode;
right?: TreeNode;
}
使用场景建议
优先使用interface的情况
- 定义对象结构:当你需要定义一个对象应该具有哪些属性和方法时
- 需要扩展性:当你需要继承其他类型定义时
- 需要声明合并:当你需要在多个地方定义同一接口的不同部分时
- 定义库的公共API:因为interface支持声明合并,更适合库的扩展
// 定义用户对象结构
interface User {
id: number;
name: string;
email: string;
}
// 扩展用户接口
interface AdminUser extends User {
permissions: string[];
}
优先使用type的情况
- 定义联合类型:当你需要定义多个可能的类型时
- 定义元组类型:当你需要定义固定长度和类型的数组时
- 定义函数类型:当你需要为函数定义类型时
- 定义复杂类型别名:当你需要为复杂类型创建简短的别名时
// 联合类型
type Direction = "up" | "down" | "left" | "right";
// 元组类型
type Coordinate = [number, number];
// 函数类型
type EventHandler = (event: Event) => void;
// 复杂类型别名
type ApiResponse<T> = {
data: T;
status: number;
message: string;
timestamp: Date;
}
实际应用示例
React组件Props定义
在React中,通常使用interface来定义组件的props:
interface ButtonProps {
children: React.ReactNode;
variant?: "primary" | "secondary" | "danger";
size?: "small" | "medium" | "large";
onClick?: () => void;
}
const Button: React.FC<ButtonProps> = ({
children,
variant = "primary",
size = "medium",
onClick
}) => {
// 组件实现
}
Redux状态类型定义
在Redux中,通常使用type来定义action类型和状态:
// Action类型
type ADD_TODO = {
type: "ADD_TODO";
payload: {
id: number;
text: string;
};
};
type REMOVE_TODO = {
type: "REMOVE_TODO";
payload: {
id: number;
};
};
type TodoAction = ADD_TODO | REMOVE_TODO;
// State类型
type TodoState = {
todos: Array<{
id: number;
text: string;
completed: boolean;
}>;
};
总结
| 特性 | interface | type |
|---|---|---|
| 对象结构定义 | ✅ | ✅ |
| 扩展性 | 通过extends | 通过& |
| 声明合并 | ✅ | ❌ |
| 类实现 | ✅ | ✅ |
| 联合类型 | ❌ | ✅ |
| 元组类型 | ❌ | ✅ |
| 基本类型别名 | ❌ | ✅ |
| 循环引用 | ✅ | 有限支持 |
在实际开发中,可以根据具体需求选择使用interface还是type:
- 对于对象结构定义,两者基本等价,但interface更符合面向对象的思想
- 对于复杂类型操作,type更灵活
- 对于库的公共API,interface更适合,因为它支持声明合并
- 对于应用内部的类型定义,可以根据团队习惯和个人偏好选择
总的来说,interface更适合定义对象的"形状",而type更适合创建类型的"别名"。
