别再死记硬背了!用几个真实代码片段,帮你彻底搞懂TypeScript的interface和type
别再死记硬背了用几个真实代码片段帮你彻底搞懂TypeScript的interface和type刚接触TypeScript时interface和type这两个概念就像一对双胞胎让人傻傻分不清楚。官方文档的抽象解释看了一遍又一遍可一到实际项目中还是不知道该用哪个。今天我们就用几个真实项目中的代码片段通过改代码看效果的方式让你在动手实践中彻底掌握它们的区别。1. 从Ant Design Vue看interface的声明合并打开Ant Design Vue的源码你会发现大量interface的使用场景。比如在button.ts中Button组件的Props定义是这样的export interface ButtonProps { size?: large | default | small; type?: primary | ghost | dashed | link | text; } export interface ButtonProps { loading?: boolean | { delay?: number }; disabled?: boolean; }动手实验尝试把第二个ButtonProps改为type定义观察TypeScript给出的错误提示你会发现使用type时会报错Duplicate identifier ButtonProps。这就是interface独有的声明合并特性——同名的interface会自动合并而type不允许重复定义。实际应用场景在大型项目中当不同模块需要扩展同一个类型定义时interface的这种特性就非常有用。比如// user模块定义基础用户类型 interface User { name: string; age: number; } // admin模块扩展用户类型 interface User { permissions: string[]; }2. API响应处理type的联合类型优势处理API响应时我们经常需要表示成功或失败的联合类型。看看这个真实场景type ApiResponseT | { status: success; data: T; timestamp: number } | { status: error; message: string; code: number }; function handleResponse(response: ApiResponseUser) { if (response.status success) { console.log(response.data); // 类型安全 } else { console.error(response.message); } }为什么这里用typeinterface无法直接表示或的关系联合类型配合类型守卫(type guard)能实现完美的类型收窄进阶技巧当需要基于现有类型创建新类型时type的条件类型特别强大type NullableT T | null; type PromisifyT PromiseT;3. 组件Props定义interface vs type实战对比在React/Vue组件开发中Props的类型定义既可以用interface也可以用type。让我们对比两种写法// 方案A: interface interface ModalProps { visible: boolean; title?: string; onClose: () void; } // 方案B: type type ModalProps { visible: boolean; title?: string; onClose: () void; };看似相同实则差异interface更适合扩展interface FullScreenModalProps extends ModalProps { fullScreen: boolean; }type更适合复杂组合type Theme light | dark; type ThemedModalProps ModalProps { theme: Theme; };团队规范建议如果组件库需要频繁扩展优先使用interface如果需要大量类型运算优先使用type。4. 高级类型体操type的独门绝技当我们需要进行复杂类型操作时type展现出不可替代的优势。看这个从axios源码简化而来的例子type Method get | post | put | delete; type RequestConfigM extends Method { method: M; url: string; } (M extends get | delete ? { params: any } : { data: any }); function requestM extends Method(config: RequestConfigM) { // 实现... } // 使用时类型检查非常精确 request({ method: get, url: /api, params: {} }); // ✅ request({ method: post, url: /api, data: {} }); // ✅ request({ method: get, url: /api, data: {} }); // ❌ 错误关键点解析使用条件类型实现方法相关的参数校验interface无法实现这种动态类型计算这种模式在复杂工具库中非常常见另一个实用技巧模板字面量类型type EventName click | hover; type HandlerName on${CapitalizeEventName}; // 结果是: onClick | onHover5. 性能与最佳实践关于interface和type的性能差异社区有一些误解。通过实测可以得出内存占用简单类型无显著差异大型项目interface可能略优因为类型检查器会缓存接口声明编译速度小型项目无感超大型项目复杂type可能稍慢实际建议保持一致性团队内部统一规范按需选择需要声明合并 → interface需要类型运算 → type不必过度优化除非性能确实成为瓶颈在Vue 3源码中我们可以看到两者混合使用的典范// 基础形状用interface interface ComponentOptions { // ... } // 复杂类型运算用type type ComponentPublicInstance /* 复杂的类型运算 */;