【TypeScript】类型别名(Type Alias)与接口类型(Interface)
类型别名(Type Alias)与接口类型(Interface)
🆚 核心异同点对比表
特性 | 类型别名 (type ) | 接口 (interface ) |
---|---|---|
声明方式 | type Name = ... | interface Name { ... } |
适用类型 | 任意类型(原始值、联合、元组等) | 主要对象类型 |
扩展方式 | 交叉类型 & | extends 继承 |
实现(implements) | 类可实现 | 类可实现 |
合并声明 | ❌ 不允许 | ✅ 自动合并同名接口 |
计算属性 | ✅ 支持 | ❌ 不支持 |
映射类型 | ✅ 支持 | ❌ 不支持 |
性能 | 更适合复杂类型操作 | 更适合对象结构定义 |
🧩 相同点
1. 都可以描述对象类型
// 使用 type
type PersonT = {name: string;age: number;
};// 使用 interface
interface PersonI {name: string;age: number;
}
2. 都可以被类实现
class Student implements PersonT, PersonI {name: string;age: number;constructor(name: string, age: number) {this.name = name;this.age = age;}
}
3. 都可以扩展
// type 扩展
type EmployeeT = PersonT & { jobTitle: string };// interface 扩展
interface EmployeeI extends PersonI {jobTitle: string;
}
🎯 不同点详解
1. 类型别名更灵活
类型别名可以定义任何类型,而接口主要用于对象类型:
// 原始类型别名
type ID = string | number;// 元组类型
type Point = [number, number];// 联合类型
type Status = 'active' | 'inactive';// 这些用interface无法实现
2. 接口声明合并
接口支持自动合并,类型别名会报错:
interface User {name: string;
}interface User {age: number;
}// 最终 User 接口包含 name 和 age
const user: User = { name: 'Alice', age: 30 };// type 会报错
type UserT = { name: string };
type UserT = { age: number }; // ❌ 错误:重复标识符
3. 性能差异
- 接口:TS 会缓存接口,检查更快
- 类型别名:每次使用时都会重新计算,复杂类型可能影响性能
🛠️ 何时使用哪种?
使用 interface
当:
- 定义对象形状(尤其是需要被类实现的契约)
interface Serializable {serialize(): string; }
- 需要声明合并扩展第三方类型
- 开发公共库的类型定义(更友好提示)
使用 type
当:
- 需要定义联合、交叉或元组类型
type Result = Success | Error;
- 需要使用映射类型或条件类型
type Nullable<T> = T | null;
- 需要定义复杂类型计算
type KeysOfType<T, U> = {[K in keyof T]: T[K] extends U ? K : never }[keyof T];
🔧 高级技巧
1. 互相组合使用
interface Base {id: string;
}type WithTimestamps<T extends Base> = T & {createdAt: Date;updatedAt: Date;
};type User = WithTimestamps<Base>;
2. 类型提取实用类型
interface ApiResponse<T> {data: T;error: string | null;
}type ResponseData<T> = T extends ApiResponse<infer U> ? U : never;
3. 基于接口创建映射类型
interface Product {id: string;name: string;price: number;
}type ReadonlyProduct = Readonly<Product>;
type PartialProduct = Partial<Product>;