很多同学在写 TS 时总会纠结定义对象结构到底用type还是interface面试也总被问到它们的区别。其实答案不是一句“都能用”那么简单而是藏在真实的开发场景里。今天我们就用实战代码 踩坑经验把这个问题彻底讲透让你以后再也不用纠结。一、它们的共同起点都能定义对象结构先看一段最熟悉的代码interface User { name: string; age: number; avatarUrl: string; } type UserType { name: string; age: number; avatarUrl: string; }; const u1: User { name: 张三, age: 18, avatarUrl: https://example.com/avatar.jpg }; const u2: UserType { name: 李四, age: 20, avatarUrl: https://example.com/avatar.jpg };你会发现在这个层面interface和type几乎可以无缝互换。它们都可以约束对象、变量用于函数参数和返回值这才是最迷惑人的地方——如果只是定义个简单的对象用谁都行。真正的区别藏在“变化”里。二、第一个分歧接口可以声明合并type 不行这是面试几乎必问的点。接口有一个非常“动态”的特性同名接口会自动合并。interface Animal { name: string; } // 其他地方甚至另一个文件里 interface Animal { age: number; } const dog: Animal { name: 三寸钉, age: 2 }; // 完全合法这种“声明合并”在做第三方库的类型扩充时特别有用。比如你想给 Vue 的组件实例上加一个自定义属性就可以利用这个特性。而type是静态的别名绝对不能重名type AnimalType { name: string }; // ❌ 报错标识符“AnimalType”重复 type AnimalType { age: number };说白了interface是开放的type是封闭的。记住这个特性在需要扩展第三方类型的时候你会感谢它。三、第二个分歧继承方式不一样面向对象里“继承”是复用结构的重要手段。两者都能实现但语法和组合能力不同。interface用extends关键字符合经典的 OOP 直觉interface Person { name: string; } interface Employee extends Person { job: string; } const e1: Employee { name: cjz, job: 字节Agent开发工程师 };type则用交叉类型来实现类似继承type PersonType { name: string }; type EmployeeType PersonType { job: string }; const e2: EmployeeType { name: lg, job: 大厂 };从结果看似乎一样但当类型复杂时的能力更强——它能一次性组合多个类型包括联合类型、函数类型等而extends只能继承静态已知的结构。四、最核心的差异type 能描述“非对象”类型这是type的主场。很多情况下我们要定义的根本不是一个对象// 联合类型 type ID string | number; // 元组类型 type Point [number, number]; // 函数签名更简洁 type AddType (a: number, b: number) number;你没办法用interface直接定义string | number这种联合类型因为接口只能表达对象形状。你可能会想尝试// ❌ 语法错误 interface ID string | number;所以当你需要一个灵活的、跨类型的别名时请直接选type。五、函数类型表面相似实则各有优势两者都可以定义函数类型// interface 写法像一个对象里藏了个调用签名 interface AddFn { (a: number, b: number): number; } // type 写法更像个箭头函数直观 type AddType (a: number, b: number) number; const add1: AddFn (x, y) x y;初看只是语法糖的区别但type在描述函数重载和组合函数类型时配合条件类型、泛型会更加灵活。而interface定义函数的写法其实更贴合 JS 里“函数也是对象”的原始设计——你可以在签名旁边再挂载一些属性。不过日常开发中绝大多数场景用type定义函数更简洁。一个朴素的经验法则单看函数用type涉及可调用对象的完整描述考虑interface。六、实战选型别争了看场景技巧interface 是给“协议”用的type 是给“数据”用的。在实际的 React/Vue 开发中最能体现这个原则。看看下面这个 React 组件// 定义一个实体的接口将来可能扩展、可能让别的模块实现 interface User { name: string; age: number; avatarUrl: string; } // 组件的 Props 也是一个“契约” interface UserCardProps { user: User; onEdit: (id: number) void; } const UserCard: React.FCUserCardProps ({ user, onEdit }) { return ( div h1User Card/h1 /div ); };在这里User和UserCardProps都是明确的“协议”——它们描述了组件和外界交互的形状。用interface来定义可以享受声明合并的便利比如未来要给User加字段也能清晰地表达“我是接口”。反观一些临时的工具类型、数据转换类型直接用type快速组合typescripttype UserBrief PickUser, name | avatarUrl; type Status loading | success | error;七、总结让我们把核心区别浓缩成一张表特性interfacetype描述对象结构✅✅声明合并同名自动合并✅❌同名报错继承方式extends交叉类型定义联合/元组等非对象类型❌✅函数类型定义调用签名箭头语法更简洁适用场景契约、组件 Props、可扩展的类型工具类型、联合类型、临时别名最重要的建议其实只有一句话定义对象形状用interface除非你需要联合类型或复杂映射——那时再用type。这样选既符合 TypeScript 的 OOP 基因也能在大型项目中保持类型的一致性和可扩展性。好了下次面试官再问你这个问题相信你已经胸有成竹。记住技术选型没有绝对的对错关键是让你的代码意图更清晰让协作的人少一些困惑。