TypeScript入门到精通——TypeScript类型系统基础——类型别名
类型别名
如同接口声明能够为对象类型命名,类型别名声明能够为 TypeScript 中的任意类型命名。
一、类型别名声明
类型别名声明能够定义一个类型别名,它的基本语法如下所示:
type AliasName = Type
在该语法中,type 是声明类型别名的关键字;AliasName 表示类型别名的名称;Type 表示类型别名关联的具体类型。
类型别名的名称必须为合法的标识符。由于类型别名表示一种类型,因此类型别名的首字母通常要大写。同时需要注意,不能使用 TypeScript 内置的类型名作为类型别名的名称,例如 boolean、number 和 any 等。下例中,我们声明了一个类型别名 Point,它表示包含两个属性的对象类型:
type Point = {x: number; y: number}
类型别名引用的类型可以为任意类型,例如原始类型、对象类型、联合类型和交叉类型等。示例如下:
type StringType = string; type BooleanType = true | false; type Point = {x: number; y: number; z?:number};
类型别名不会创建出一个新的类型,它只是给已有类型命名并直接引用该类型。在程序中,使用类型别名与直接使用该类型别名引用的类型是完全相等的,这个和go语言有相似也有不同。
-
- 语法:在 Golang 中,类型别名的语法是使用 type 关键字,例如 type MyInt int。而在 TypeScript 中,类型别名的语法是使用 type 关键字后跟等号,例如 type MyString = string。
- 本质:Golang 的类型别名是一个新的类型,它与原始类型并不完全相等。类型别名之间不能进行类型转换操作。而 TypeScript 的类型别名只是给原始类型起了一个新的名字,它们本质上是相同的类型。
- 兼容性:由于 Golang 的类型别名和原始类型并不完全相等,因此它们之间可能存在一些兼容性问题。而 TypeScript 的类型别名与原始类型完全兼容,可以互相替换使用。
Golang 的类型别名更像是一种类型的封装或重命名,而 TypeScript 的类型别名则更像是一种类型的别名或引用。
二、递归的类型别名
一般情况下,在类型别名声明中赋值运算符右侧的类型不允许引用当前定义的类型别名。因为类型别名对其引用的类型使用的是及早求值的策略,而不是惰性求值的策略。因此,如果类型别名引用了自身,那么在解析类型别名时就会出现无限递归引用的问题。
以下是一个示例代码,演示了 TypeScript 中类型别名引用自身导致无限递归引用的问题:
type MyType = { value: MyType; };
在上述代码中,MyType 类型别名引用了自身,这导致了无限递归引用的问题。因为 MyType 的定义中包含了 MyType 本身,所以 TypeScript 在解析 MyType 时会不断展开别名的定义,直到达到最大递归限制,导致编译错误。
为了避免这种情况,我们需要避免在类型别名的声明中引用当前定义的类型别名本身。如果需要使用类似的结构,可以考虑使用接口(interface)或类型字面量等方式进行定义。
三、类型别名与接口
类型别名与接口相似,它们都可以给类型命名并通过该名字来引用表示的类型。虽然在大部分场景中两者都是可以互相转换的,但类型别名和接口之间还是存在一些差别。
区别一,类型别名能够表示非对象类型,而接口则只能表示对象类型。因此,当我们想要表示原始类型、联合类型和交叉类型等类型时只能使用类型别名。
区别二、接口可以继承其他接口、类型对象类型,而类型别名则不支持继承。
区别三、接口名总是会显示在编译器的诊断信息和代码编辑器的智能提示信息中,而类型别名的名字只在特定情况下才会显示出来。
区别四、接口具有声明合并的行为,而类型别名则不会进行声明合并。