2、TypeScript的类型系统
基础类型
基础类型包括String
、number
、boolean
1 | // 通过冒号标注变量值的类型 |
空和未定义类型
1 | let a: null |
如果声明了一个变量,但没有赋值,那么值默认为
undefined
,类型为any
避免赋值为空值时的配置
修改tsc配置文件,加入字段strictNullChecks
1 | { |
此时就不能将空值赋值给其他变量
对象类型
内置对象
1 | // 数组 |
自定义对象类型
自定义对象相较于内置对象的优点是复用性高。但其不能作为值,interface
只存在于编译前,编译后是不存在的。
1 | interface Person { |
也可以通过对象定义
1 | class Person { |
通过对象定义可以作为值使用。因此当只作为某个函数接收的参数结构,可以使用interface
1 | interface Person { |
包装类型
1 | let str1: string |
数组类型
Typescript
中数组存储的类型必须一致,所以在标注数组类型的时候,同时要标注数组中存储的数据类型
1 | // 泛型标注 |
元组类型
元组类型与数组类似,但可以存储不同类型。
1 | // 元组类型中初始化时,值与类型必须一一匹配 |
枚举类型
数字枚举
枚举的作用组织收集一组关联数据的方式,通过枚举我们可以给一组有关联意义的数据賦予一些友好的名字
1 | // 枚举类型一旦定义无法在被赋值 |
注意事项:
- key 不能是数字
- value 可以是数字,称为 数字类型枚举,也可以是字符串,称为 字符串类型枚举,但不能是其它值,默认为数字:0
- 枚举值可以省略,如果省略,则:
- 第一个枚举值默认为:0
- 非第一个枚举值为上一个数字枚举值 + 1
- 枚举值为只读(常量),初始化后不可修改
字符串类型枚举
枚举类型的值,也可以是字符串类型
1 | enum URLS { |
注意:如果前一个枚举值类型为字符串,则后续枚举项必须手动赋值
小技巧:枚举名称可以是大写,也可以是小写,推荐使用全大写(通常使用全大写的命名方式来标注值为常量)
无值类型
表示没有任何数据的类型,通常用于标注无返回值函数的返回值类型,函数默认标注类型为:void
1 | function fn():void { |
在
strictNullChecks
为false
的情况下,undefined
和null
都可以赋值给void
,但是当strictNullChecks
为true
的情况下,只有undefined
才可以赋值给void
Never类型
当一个函数永远不可能执行 return
的时候,返回的就是 never
,与 void 不同,void
是执行了 return
, 只是没有值,never
是不会执行 return
,比如抛出错误,导致函数终止执行
1 | function fn(): never { |
任意类型
1 | let any1: any |
有的时候,我们并不确定这个值到底是什么类型或者不需要对该值进行类型检测,就可以标注为 any
类型
1 | let a: any; |
- 一个变量申明未赋值且未标注类型的情况下,默认为
any
类型 - 任何类型值都可以赋值给
any
类型 any
类型也可以赋值给任意类型any
类型有任意属性和方法
注意:标注为 any
类型,也意味着放弃对该值的类型检测,同时放弃 IDE 的智能提示
小技巧:当指定
noImplicitAny
配置为true
,当函数参数出现隐含的any
类型时报错
未知类型
unknow,3.0 版本中新增,属于安全版的 any,但是与 any 不同的是:
- unknow 仅能赋值给 unknow、any
- unknow 没有任何属性和方法
函数类型
在 JavaScript 函数是非常重要的,在 TypeScript 也是如此。同样的,函数也有自己的类型标注格式
- 参数
- 返回值
1 | 函数名称( 参数1: 类型, 参数2: 类型... ): 返回值类型; |
1 | function add(x: number, y: number): number { |
类型保护
我们通常在JavaScript
中通过判断来处理⼀些逻辑,在TypeScript
中这种条件语句块还有另外⼀个特性:根据判断逻辑的结果,缩⼩类型范围(有点类似断⾔),这种特性称为 类型保护,触发条件:
- 逻辑条件语句块:if、else、elseif
- 特定的⼀些关键字:typeof、instanceof、in……
typeof
1 | function fn(a: string | number) { |
instanceof
1 | function fn(a: Date|Array<any>) { |
in
1 | interface IA { |
字面量类型保护
1 | interface IA { |
自定义类型保护
1 | function canEach(data: any): data is Element[]|NodeList { |
data is Element[]|NodeList
是⼀种类型谓词,格式为: xx is XX
,返回这种类型的函数就可以被TypeScript
识别为类型保护
类型操作
typeof
在 TypeScript 中, typeof
有两种作⽤
- 获取数据的类型
- 捕获数据的类型
1 | let str1 = 'xiaokang.me' |
keyof
1 | let p1 = { |
in
1 | interface Personal { |
in 后⾯的类型值必须是string
或者number
或者symbol
类型兼容
TypeScript
的类型系统是基于结构⼦类型的,它与名义类型(如:java
)不同(名义类型的数据类型兼容性或等价性是通过明确的声明或类型的名称来决定的)。这种基于结构⼦类型的类型系统是基于组 成结构的,只要具有相同类型的成员,则两种类型即为兼容的。
1 | class Person { |