选 type 还是 interface 取决于需求:需可扩展或可实现时用 interface,如类 implements、声明合并、API 入口;做类型运算或描述非对象结构时优先用 type,如联合、交叉、函数类型;二者可互换但影响演进能力。

选 type 还是 interface,关键看你要解决什么问题:不是语法能不能写出来,而是类型系统是否需要它“可扩展”或“可实现”。
什么时候必须用 interface
当类型要被类 implements 时,只能用 interface。TypeScript 不允许类实现 type 别名。
- 比如定义一个通用的“可销毁”契约:interface Disposable { dispose(): void },后续多个类(如 DatabaseConnection、Timer)都可 implements Disposable
- 需要声明合并(多次声明同名 interface,TS 自动合并成员)——适合大型项目中由不同模块共同完善一个类型定义,例如库的全局配置接口
- 作为公共 API 的入口点,强调“结构约定”和“未来可扩展性”,比如前端 SDK 暴露的 interface RequestConfig,用户可在自己代码里再声明同名 interface 补充字段
什么时候优先用 type
当你在做类型“运算”或描述非对象结构时,type 是唯一或更自然的选择。
- 定义联合类型:type Status = 'loading' | 'success' | 'error'(interface 无法表达字面量联合)
- 定义交叉类型:type AdminUser = User & { role: 'admin'; permissions: string[] }
- 给函数、元组、映射类型、条件类型起别名:type EventHandler
= (e: T) => void 或 type KeysOf= keyof T - 简化重复出现的复杂类型,比如 type ApiResponse
= { data: T; code: number; message: string } ,纯属复用,不打算被继承或合并
能互换但有隐含代价的场景
单个对象形状定义(如 { id: number; name: string })两者都支持,但选择影响后续演进能力。
- 用 interface:以后加字段、被其他 interface extends、被类 implements 都很顺畅
- 用 type:一旦写成 type User = { id: number } & Profile,就失去了声明合并能力;想“扩展”只能靠交叉(type ExtendedUser = User & { avatar: string }),但无法让已有变量自动获得新字段
- 注意:interface 可以 extends type,type 也可以 & interface —— 它们可以混合使用,不必非此即彼
各自明确的局限
- interface 局限:不能定义基本类型别名(interface MyString extends string ❌)、不能直接表达联合/元组/映射类型、不能用于类型守卫中的 typeof 或 in 检查的右侧(需配合类型谓词)
- type 局限:不支持声明合并、不能被 implements、错误提示有时不如 interface 清晰(尤其在嵌套交叉时)、在 .d.ts 声明文件中若用于导出公共类型,消费者无法对其做 interface-style 扩展


















