多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[TOC] >[success] # 类型别名,字面量 和 交叉类型 本章节 **查漏补缺** ,讲一些零碎的小 **概念** 。 >[success] ## 类型别名(type aliase) **类型别名**: 听名称就很好理解,就是**给类型起一个别的名字** 。 1. **约束函数** 例子:比如说有一个 **[函数类型](https://www.kancloud.cn/wangjiachong/vue_notes/2165549)** ,要多次用到这个 **函数类型(等号左侧是函数类型)** ,就要 **多次声明同样的函数类型** ,就会很累,产生相同不必要的代码,如下: **index.ts** ~~~ // let 函数名称: 函数类型 = 函数函数内部逻辑代码 let sum1: (x:number, y:number) => number = (x:number, y:number):number => x + y // 使用函数 const result1 = sum1(1, 2) // 下面的函数中再次声明了 (x:number, y:number) => number // 再次声明【函数类型】 let sum2: (x:number, y:number) => number = (x:number, y:number):number => x * y // 使用函数 const result2 = sum2(3, 2) ~~~ 上面的代码中 **多次声明了函数类型** ,此时我们可以使用 **type** 关键字来创建一个 **类型别名** ,来解决这个问题,代码如下: **index.ts** ~~~ // 用type关键字,创建【类型别名】 type PlusType = (x:number, y:number) => number // 使用【类型别名】创建函数 let sum1: PlusType = (x:number, y:number):number => x + y // 使用函数 const result1 = sum1(1, 2) // 使用【类型别名】创建函数 let sum2: PlusType = (x:number, y:number):number => x * y // 使用函数 const result2 = sum2(3, 2) ~~~ 我们也可以使用 [Interface 约束函数](https://www.kancloud.cn/wangjiachong/vue_notes/2165549) ,效果是一样的。 2. **约束变量** **index.ts** ~~~ // 用【类型别名】来【约束联合类型】 type StrOrNumber = string | number // 使用类型别名 let result:StrOrNumber = 123 // 赋值成字符串 result = '哈哈哈' ~~~ 如果赋值成 **Boolean** 类型值的话,就会报错。 >[success] ## 字面量 **字面量** 是一个**特殊的类型** ,这个类型只能是 **原始数据类型** ,举个例子,下面代码中 **约束的类型是字符串name,值也只能等于name,约束的类型是1,值也只能等于1** ,不然会报错。 **index.ts** ~~~ const str: 'name' = 'name' const number: 1 = 1 ~~~ **字面量** 应用场景是什么?我们经常会使用 **枚举(Enum)** 来储存 **常量值(比如说我们四个方位:上、下、左、右)** ,而 **字符串** 、 **字面量** 是用这种简单的方式,来处理这种情形,如下: **index.ts** ~~~ // 用【类型别名】定义【字符串类型】 type Directions = 'Up' | 'Down' | 'Left' | 'Right' // 使用【字符串类型】做【字面量】 let toWhere: Directions = 'Down' ~~~ **编辑器图片**: ![](https://img.kancloud.cn/b3/7b/b37ba4270674077e451045eac273da12_497x227.png) 这样写有一个好处,它会把 **类型限定在里面,并且在编辑器上会有提示** ,非常方便 。 >[success] ## 交叉类型 **或(符合: | )** 在 **ts** 中叫 **联合类型** ,有一个与他相对应的类型,**和(符合: & )** 叫做 **交叉类型** ,在 **ts** 中使用代码人如下: ~~~ // 定义接口 interface IName { name: string } // 定义类型别名 type IPerson = IName & { age: number } // 定义对象 let person:IPerson = { name: '小明', age: 18 } ~~~ **对象** 中必须要有 **name** 与 **age** ,否则报错,它跟 **接口(interface)** 的 **继承(extends)** 非常相似,它们都是为了 **实现对象形状的组合和扩展** 。 >[success] ## 接口(interface) 与 类型别名(type) 该用哪个? 我们讲一下什么时候使用 **interface** 什么时候使用 **type** 。 1. **类型别名(type)** :**type** 作为 **类型别名** ,是一种非常灵活宽泛的概念, **它不是一种特殊的类型,只是别的类型的一个别名** ,有点像 **快捷方式** ,**当你要使用交叉类型时,可以考虑使用type** 。 2. **接口(interface)** :**接口(interface)** 是一种独特的类型,当你要实现 **extends** 或者实现 **类(Class)** 的 **implements** 时,可以考虑使用 **接口(interface)** 。