TypeScript 中的类型(上)
JS/TS 中有哪些数据类型
![](/images/typescript/ts-2/ts_2_01.png)
用集合来理解 TS 数据类型
![](/images/typescript/ts-2/ts_2_06.png)
number
可看做 1、1.1、2、2.3 等所有数字值组成的集合string
可看做 a、b、ab、c、abc 等所有字符串值组成的集合boolean
可看做 true
和 false
这两个值组成的集合
![](/images/typescript/ts-2/ts_2_07.png)
![](/images/typescript/ts-2/ts_2_08.png)
![](/images/typescript/ts-2/ts_2_09.png)
JS 中的 Number
、String
、Boolean
只用于包装对象,一般不会用到它们;同样地在 TS 中也不会用到它们。
TS 中一般不会用 Object
来描述对象的类型,因为 Object
所表示的类型范围太大了
![](/images/typescript/ts-2/ts_2_10.png)
如何用 TS 来描述对象
![](/images/typescript/ts-2/ts_2_05.png)
- 用
class
/constructor
描述 - 用
type
/interface
描述
描述普通对象
由于 object
/Object
太不精确,所以一般使用索引签名或Record 泛型来描述普通对象
使用索引签名
![](/images/typescript/ts-2/ts_2_02.png)
思考题:key 的类型可以不是 string 吗?
经测试,k
的类型只能为 number
、string
、symbol
这三种
使用 Record
![](/images/typescript/ts-2/ts_2_03.png)
使用具体的字段
1 | type A = { |
描述数组对象
由于 Array
太不精确,所以一般用 Array<?>
或 string[]
或 [string, number]
来描述数组
![](/images/typescript/ts-2/ts_2_04.png)
思考题
1 | type A = [1, 2, 3] |
以上 TS 代码中 a 的值是?
当于只有一个元素的集合,因此 a
的值只能是 [1, 2, 3]
描述函数对象
由于 Function
太不精确,所以一般用 () => ?
来描述函数
1 | type FnA = (a: number, b: number) => number; |
带有 this
的函数声明
1 | type Person = {name: string, age: number, sayHi: FnWithThis} |
描述其他对象
直接用 class
(构造函数) 描述即可
1 | const d: Date = new Date(); |
any、unknown、never 是什么
从集合的角度理解:any
是全集,never
是空集,unknown
是未知集
TS 的绝大部分规则对 any
类型不生效(TS 不报错)
可对 unknown
进行断言,适用于值是从外部获取的,没办法提前知道类型的情况;比如当使用 ajax
获取数据时,后台返回的数据格式不确定,此时可将接口响应的数据类型可定义为 unknown
,然后再对其进行断言
1 | const a: unknown = await ajax.get('/api/users') |
never
一般不会用来声明类型,而是用来进行类型推断的
1 | type A = string | number | boolean; |
JS 类型与 TS 类型的区别
我是这么理解的:
JS 这门语言其实并没有提供类型相关的关键字(如小写的 number
、string
、boolean
),只是提供了typeof
让我们获取变量的类型,所以我认为 JS 对类型非常不重视。
而 TS 则将 JS 中的类型提升到很高的位置,高到如果你把类型写错了代码就不能通过编译。因此这两门语言中的类型其实没有可比性,只是看起来有重叠部分而已。如果一定要比较,我会这么说:
- 粒度不同:在 JS 中的类型
number
不可再细分,而 TS 中的number
可以看做 1、1.1、2、2.3 等无数个小类型的联合 - 可变性不同:JS 中的变量类型是可变的,一个
number
随时可以变成一个string
;TS 中除了any
,其他类型要么是不可变的,要么就算可变也是有限制的