摘要:
type和interface是 TS 里最容易混淆的知识点,也是面试必考题。很多人写代码时随便混用,并不清楚二者底层差异。本文结合代码实例,搞懂两者相同点、核心区别,以及实际开发该如何选择。
前言
初学 TypeScript 的时候,面对对象类型定义,有两种写法摆在眼前:interface 和 type。很多同学觉得两者差不多,随便挑一个写就完事。但面试经常被问到:说说 type 和 interface 的区别?
只知道 "都能定义对象" 是远远不够的,它们在语法能力、合并特性、函数描述上都有明确差异。看完这篇,以后写 TS 不再纠结。
一、共同点:哪些场景两者可以互换
两者都可以描述对象结构,也都可以描述函数类型,都可以用来约束变量、函数参数、函数返回值。
1. 描述普通对象
typescript
运行
typescript
// interface 版本
interface UserInterface {
name: string
age: number
}
// type 版本
type UserType = {
name: string
age: number
}
// 使用方式完全一致
const u1: UserInterface = { name: "张三", age: 18 }
const u2: UserType = { name: "李四", age: 20 }
2. 描述函数类型
两者都可以约束函数,只是语法不一样,后面会细讲。
3. 都支持类型扩展(继承)
interface使用extends实现扩展type使用交叉类型&实现扩展
typescript
运行
typescript
// interface 扩展
interface Animal {
name: string
}
interface Dog extends Animal {
bark(): void
}
// type 扩展
type AnimalT = { name: string }
type DogT = AnimalT & { bark(): void }
小结:单纯定义普通对象,大部分场景二者可以互换。
二、核心区别(面试重点)
1. 声明合并:interface 独有的能力
interface 支持同名多次声明,TS 会自动把所有属性合并;type 严禁重复声明,直接编译报错。
✅ interface 合并示例
typescript
运行
kotlin
interface User {
name: string
}
// 再次声明同名接口,属性自动合并
interface User {
age: number
}
// 最终 User = { name:string; age:number }
const user: User = { name: "小明", age: 22 }
❌ type 重复声明直接报错
typescript
运行
typescript
type User = { name: string }
type User = { age: number }
// 报错:标识符"User"重复。
这个特性非常重要!做第三方库类型补丁、扩展全局类型的时候,只能使用
interface。type 做不到。
2. 是否可以描述非对象类型
interface 只能描述对象、函数、类这种引用结构 ,不能写基础类型、联合类型、元组。type 是类型别名,可以给任意类型起别名,能力更强。
typescript
运行
typescript
// ✅ type 支持
type Status = "success" | "error" // 联合类型
type NumAlias = number // 基础类型别名
type Point = [number, number] // 元组
// ❌ interface 下面全部报错
interface Status = "success" | "error"
interface NumAlias = number
interface Point = [number, number]
3. 函数类型的语法差异
两者都能写函数类型,但是语法不同,日常开发简单函数 type 更方便。
interface:调用签名写法,写在大括号内部
typescript
运行
typescript
interface AddFn {
(a: number, b: number): number
desc: string // 优势:直接给函数挂载额外属性
}
const add: AddFn = (x, y) => x + y
add.desc = "加法函数"
type:箭头语法,简洁直观
typescript
运行
typescript
type AddFn = (a: number, b: number) => number
// 如果需要给函数挂载属性,必须用 & 交叉,写法繁琐
type AddFnWithProp = ((a: number, b: number) => number) & { desc: string }
小记:
- interface 定义函数:返回值用
:- type 定义函数:返回值用
=>
4. 扩展冲突行为不一样
- interface 使用
extends扩展,如果子接口和父接口属性类型冲突,直接编译报错。 - type 使用
&交叉,如果属性类型冲突,不会直接报错,该字段会变成never。
typescript
运行
typescript
// interface 冲突,直接报错
interface Base { id: number }
interface A extends Base { id: string }
// type 冲突,不会报错,id 变为 never
type BaseT = { id: number }
type B = BaseT & { id: string }
三、开发怎么选?实操建议
- 需要声明合并、扩展第三方全局类型 → 选 interface
比如给 window 挂载自定义属性,只能用 interface。
typescript
运行
typescript
interface Window {
myGlobal: string
}
window.myGlobal = "123"
- 写联合类型、元组、基础类型别名 → 必须使用 type
interface 做不到,没有替代方案。
- 普通函数类型,不需要挂载额外属性 → 优先 type,箭头写法更清爽
- 普通对象类型,没有特殊需求:两者都行
社区约定:对外暴露库 API 优先 interface;业务内部类型优先 type。
四、面试背诵精简版
面试被问到:说说 type 和 interface 的区别?
**相同点:**都可以描述对象、函数结构;都可以约束变量、参数返回值;都支持类型扩展。
不同点:
- interface 支持声明合并,type 不能重复声明;
- interface 使用
extends扩展,type 使用交叉&; - type 可以定义联合、元组、基础类型别名,interface 仅支持对象类结构;
- 函数语法不一样:interface 使用调用签名,type 使用箭头;简单函数 type 更简洁;
- 属性冲突时 interface 直接报错,type 会生成 never。
结尾
很多人写 TS 凭感觉随便选,搞懂二者能力边界,写出来的类型才会规范。记住:不是哪个更好,而是哪个更适合当前场景。
补充完整测试代码块
typescript
运行
typescript
// 1. interface 对象扩展
interface Animal {
name: string
}
interface Dog extends Animal {
age: number
}
// 2. type 对象扩展
type AnimalType = { name: string }
type DogType = AnimalType & { age: number }
// 3. interface 函数类型
interface AddInterface {
(a: number, b: number): number
info: string
}
// 4. type 函数类型
type AddType = (a: number, b: number) => number
// 5. interface 声明合并
interface User {
name: string
}
interface User {
age: number
}
const user: User = { name: "测试", age: 18 }