TypeScript 接口和类型别名区别

在前端开发里,大家常会用 TypeScript 给代码“上保险”——避免变量传错类型、函数参数乱填格式。但刚学的人常会搞混接口和类型别名这两个工具,总觉得它们都是用来定义类型的,到底啥时候用哪个?

先搞懂:它们本质都是“类型契约”

不管是接口(interface)还是类型别名(type alias),核心作用都是给一段代码约定“必须是什么样子”,就像你订外卖时填的收货地址,必须有省市区、门牌号,少一样都送不到。举个例子,要定义一个“人”的类型,用接口写是这样:

TypeScript 接口和类型别名区别

`typescript

interface Person { name: string; age: number }

`

用类型别名写也差不多:

`typescript

type Person = { name: string; age: number }

`

这俩现在看起来没区别,就像你买奶茶选“去冰”,堂食和小程序点单都能实现,只是操作方式不同而已。

第一个关键区别:能不能“扩展开”

日常开发里,经常需要在原有类型上加新功能,这时候接口和类型别名的扩展方式完全不一样。

接口用的是“声明合并”——就像你买奶茶时跟老板说“加珍珠”,之后又说“加椰果”,老板会自动把要求合并,接口的同名定义也会自动合并。比如:

`typescript

interface User { id: number }

interface User { name: string } // 会自动合并成 User 有 id 和 name

`

这种场景特别适合写插件扩展,比如你用了一个UI库,想给它的全局配置加自定义字段,用接口改就很方便。

而类型别名用的是“扩展继承”——得用&符号把多个类型拼起来,就像你买奶茶时选“去冰+三分糖+加珍珠”,得把所有要求列在一起。同样定义一个带两个字段的User:

`typescript

type User = { id: number } & { name: string }

`

这种方式更适合“组合不同类型”,比如你要把“员工”和“管理员”的类型拼出“高级管理员”,用类型别名会更直观。

第二个关键区别:能定义的“类型范围”

就像你用外卖小程序,接口只能点“餐品”(对象、类的结构这类),而类型别名能点“餐品+饮品+配件”——它支持更灵活的类型组合。

比如你要定义“一个值要么是字符串,要么是数字”,这种“联合类型”只能用类型别名:

`typescript

type StringOrNumber = string | number;

`

要是用接口写,就会报错,因为接口本质是用来约定“对象形状”的。再比如,你要定义“一个对象里的属性必须是布尔值”(索引类型),也只能用类型别名:

`typescript

type BooleanMap = { [key: string]: boolean };

`

这种灵活度是接口比不了的,就像你买奶茶除了基础餐品,还能单独加配料、选甜度,而接口只能按固定套餐选。

最后给个实用选择建议

总结下来,不用纠结哪个“更好”,选对场景就行:

  • 如果是定义对象、类的结构,或者需要扩展(比如插件里改全局类型),优先用接口;
  • 如果需要定义联合类型、索引类型,或者要组合多个类型,就用类型别名。

举个实际开发的例子:做电商系统时,用户的基础信息用接口定义,方便后续加“会员等级”“收货地址”等扩展字段;而商品的状态(上架/下架/待售)这种联合类型,就用类型别名来写,一目了然。

上一篇 PHP 字符串长度怎么获取