type和interface的区别
一、语法形式
type
语法:
使用type
关键字来定义,可以定义基本类型别名、联合类型、交叉类型以及函数类型等多种复杂类型。例如:- 定义基本类型别名:这里
MyString
就是string
类型的一个别名,后续变量声明时可以用它来指定类型。 - 定义联合类型:表示
MyUnionType
这个类型可以是string
或者number
类型的值,变量value
遵循这个联合类型定义来赋值。 - 定义交叉类型:交叉类型是将多个类型合并在一起,这里
IntersectType
要求同时具备{ name: string }
和{ age: number }
的属性结构。 - 定义函数类型:
定义了一个接收
string
类型参数且无返回值的函数类型,变量myFunc
按照此函数类型进行赋值。
- 定义基本类型别名:这里
interface
语法:
通过interface
关键字来定义,主要用于定义对象类型结构,更侧重于描述对象具有哪些属性以及属性对应的类型,还可以定义可选属性、只读属性以及函数类型的属性等。例如:- 定义对象类型结构:清晰地定义了名为
Person
的对象类型,包含name
和age
两个必选属性,变量person
的赋值要符合这个对象类型要求。 - 定义可选属性:
使用
?
符号可以定义可选属性,像这里的password
就是可选的,所以在给变量user
赋值时可以只提供username
这个属性。 - 定义只读属性:通过
readonly
关键字定义只读属性,赋值后就不能再对其进行修改了。 - 定义函数类型的属性:可以在接口中定义函数类型的属性,规定对象中相应函数的参数和返回值类型。
- 定义对象类型结构:清晰地定义了名为
二、重复定义处理方式
type
重复定义:
在同一个作用域内,不允许使用相同的名称重复定义type
。例如:会直接报错,因为
type
一旦定义了某个名称的类型后,就不能再用相同名称去定义其他类型了。interface
重复定义:
同一个作用域内可以对interface
进行重复定义,并且后续的定义会自动与之前的定义进行合并。例如:先定义了Animal
接口包含name
属性,后面再次定义Animal
接口添加了age
属性,最终Animal
接口就相当于包含了name
和age
两个属性,这种特性在对一些复杂接口进行扩展时非常有用。
三、实现(implements)与继承(extends)方面
type
相关情况:type
本身不能直接用于类的继承或者实现相关操作,它主要就是定义类型别名、组合复杂类型等,更多是从类型层面去描述数据结构和函数签名等情况。例如,不能像下面这样使用type
进行类的继承:interface
相关情况:- 实现(implements):类可以实现接口,意味着类必须要实现接口中定义的所有属性和方法(函数类型属性),确保类的实例符合接口所规定的类型结构。例如:
Car
类实现了Vehicle
接口,所以必须要提供start
和stop
这两个无返回值的函数方法来满足接口要求。 - 继承(extends):接口之间可以相互继承,通过继承可以扩展已有接口的定义内容,复用之前接口定义的属性等信息。例如:
Mammal
接口继承了Animal
接口,所以Mammal
类型的对象既要满足Animal
接口中eat
方法的要求,又要具备自身定义的run
方法。
- 实现(implements):类可以实现接口,意味着类必须要实现接口中定义的所有属性和方法(函数类型属性),确保类的实例符合接口所规定的类型结构。例如:
四、适用场景
-
type
适用场景:- 复杂类型组合场景:当需要定义联合类型、交叉类型等复杂的类型组合时,
type
更加方便灵活,比如定义一个可以是字符串、数字或者布尔值的联合类型,或者将多个对象类型通过交叉类型的方式合并起来等情况,使用type
能清晰准确地表达这种复杂类型结构。 - 类型别名需求场景:如果只是想给某个已有的类型(如
string
、number
等基本类型或者一些复杂的自定义类型)取一个更简洁易懂的别名,便于后续代码中使用和类型管理,那么type
是很好的选择,例如定义一个UserId
类型别名来代表number
类型的用户 ID,使代码的类型语义更加明确。
- 复杂类型组合场景:当需要定义联合类型、交叉类型等复杂的类型组合时,
-
interface
适用场景:- 定义对象结构场景:在大多数情况下,当需要定义对象的结构,明确对象有哪些属性、属性的类型以及是否可选、只读等情况时,
interface
是更符合直觉的选择,尤其是在面向对象编程风格较为明显的代码中,用于规范类实例或者普通对象的类型组成。 - 接口扩展与复用场景:如果有多个相关的接口,需要通过继承来扩展功能或者复用已有的接口定义内容,比如在设计一个软件系统中不同层级的模块接口,通过接口继承可以很好地梳理接口之间的层次关系,便于代码的维护和扩展,此时
interface
就发挥了重要作用。
- 定义对象结构场景:在大多数情况下,当需要定义对象的结构,明确对象有哪些属性、属性的类型以及是否可选、只读等情况时,
总体而言,type
和interface
在语法、功能特点及适用场景等方面都存在差异,开发者可以根据具体的项目需求和代码设计情况来灵活选择使用它们。