6
6
7
7
### 基本含义
8
8
9
- any 类型表示该位置不限制类型,任意类型的值都可以使用 。
9
+ any 类型表示没有任何限制,该类型的变量可以赋予任意类型的值 。
10
10
11
11
``` typescript
12
12
let x: any ;
@@ -18,25 +18,32 @@ x = true; // 正确
18
18
19
19
上面示例中,变量` x ` 的类型是` any ` ,就可以被赋值为任意类型的值。
20
20
21
- 变量类型一旦设为` any ` ,TypeScript 实际上会关闭它的类型检查, 即使有明显的类型错误,只要句法正确,都不会报错。
21
+ 变量类型一旦设为` any ` ,TypeScript 实际上会关闭这个变量的类型检查。 即使有明显的类型错误,只要句法正确,都不会报错。
22
22
23
23
``` typescript
24
24
let x: any = ' hello' ;
25
- x (1 ) // 正确
26
- x .foo = 100 ; // 正确
25
+
26
+ x (1 ) // 不报错
27
+ x .foo = 100 ; // 不报错
27
28
```
28
29
29
30
上面示例中,变量` x ` 的值是一个字符串,但是把它当作函数调用,或者当作对象读取任意属性,TypeScript 编译时都不报错。原因就是` x ` 的类型是` any ` ,TypeScript 不对其进行类型检查。
30
31
31
- 实际项目中,` any ` 类型往往用于关闭某些变量的类型检查。由于这个原因,应该尽量避免使用` any ` 类型,否则就失去了使用 TypeScript 的意义。
32
+ 由于这个原因,应该尽量避免使用` any ` 类型,否则就失去了使用 TypeScript 的意义。
33
+
34
+ 实际开发中,` any ` 类型主要适用以下两个场合。
32
35
33
- 这个类型的主要设计目的,是为了适配以前老的 JavaScript 项目的迁移。有些年代很久的大型 JavaScript 项目,尤其是别人的代码,很难为每一行适配正确的类型,这时你为那些类型复杂的变量加上` any ` ,TypeScript 编译时就不会报错。不过,这大概是` any ` 唯一的适用场合。
36
+ (1)出于特殊原因,需要关闭某些变量的类型检查,就可以把该变量的类型设为` any ` 。
37
+
38
+ (2)为了适配以前老的 JavaScript 项目,让代码快速迁移到 TypeScript,可以把变量类型设为` any ` 。有些年代很久的大型 JavaScript 项目,尤其是别人的代码,很难为每一行适配正确的类型,这时你为那些类型复杂的变量加上` any ` ,TypeScript 编译时就不会报错。
34
39
35
40
总之,TypeScript 认为,只要开发者使用了` any ` 类型,就表示开发者想要自己来处理这些代码,所以就不对` any ` 类型进行任何限制,怎么使用都可以。
36
41
42
+ 从集合论的角度看,` any ` 类型可以看成是所有其他类型的全集,包含了一切可能的类型。TypeScript 将这种类型称为“顶层类型”(top type),意为涵盖了所有下层。
43
+
37
44
### 类型推断问题
38
45
39
- ` any ` 类型的另一个出现场景是,对于那些开发者没有指定类型 、TypeScript 必须自己推断类型的变量,如果这时无法推断出类型 ,TypeScript 就会认为该变量的类型是` any ` 。
46
+ 对于开发者没有指定类型 、TypeScript 必须自己推断类型的那些变量,如果无法推断出类型 ,TypeScript 就会认为该变量的类型是` any ` 。
40
47
41
48
``` typescript
42
49
function add(x , y ) {
@@ -46,17 +53,17 @@ function add(x, y) {
46
53
add (1 , [1 , 2 , 3 ]) // 正确
47
54
```
48
55
49
- 上面示例中,函数` add() ` 的参数变量` x ` 和` y ` ,都没有足够的信息,TypeScript 无法推断出它们的类型,就会认为这些变量的类型是 ` any ` 。以至于后面就不再对函数` add() ` 进行类型检查了,怎么用都可以。
56
+ 上面示例中,函数` add() ` 的参数变量` x ` 和` y ` ,都没有足够的信息,TypeScript 无法推断出它们的类型,就会认为这两个变量和函数返回值的类型都是 ` any ` 。以至于后面就不再对函数` add() ` 进行类型检查了,怎么用都可以。
50
57
51
- 这显然是很糟糕的情况,所以对于那些类型不明显的变量,一定要明确声明类型,防止推断为 ` any ` 。
58
+ 这显然是很糟糕的情况,所以对于那些类型不明显的变量,一定要显式声明类型,防止被推断为 ` any ` 。
52
59
53
- TypeScript 提供了一个编译选项` --noImplicitAny ` ,只要打开这个选项,推断不出类型就会报错 。
60
+ TypeScript 提供了一个编译选项` --noImplicitAny ` ,打开该选项,只要推断出 ` any ` 类型就会报错 。
54
61
55
62
``` bash
56
63
$ tsc --noImplicitAny app.ts
57
64
```
58
65
59
- 上面命令就使用了 ` --noImplicitAny ` 编译选项进行编译,这时上面的函数` add() ` 就会报错。
66
+ 上面命令使用了 ` --noImplicitAny ` 编译选项进行编译,这时上面的函数` add() ` 就会报错。
60
67
61
68
### 污染问题
62
69
@@ -72,21 +79,21 @@ y * 123 // 正确
72
79
y .toFixed () // 正确
73
80
```
74
81
75
- 上面示例中,变量` x ` 的类型是` any ` ,实际的值是一个字符串。数值类型的变量 ` y ` 被赋值为 ` x ` ,也不会报错 。然后,变量` y ` 继续进行各种数值运算,TypeScript 也检查不出错误,问题就这样留到运行时才会暴露。
82
+ 上面示例中,变量` x ` 的类型是` any ` ,实际的值是一个字符串。变量 ` y ` 的类型是 ` number ` ,表示这是一个数值变量,但是它被赋值为 ` x ` ,这时并不会报错 。然后,变量` y ` 继续进行各种数值运算,TypeScript 也检查不出错误,问题就这样留到运行时才会暴露。
76
83
77
84
污染其他具有正确类型的变量,把错误留到运行时,这就是不宜使用` any ` 类型的另一个主要原因。
78
85
79
- ### 顶端类型
86
+ ### 顶层类型
80
87
81
- 前面说过,` any ` 类型可以被赋值为任何类型的值。在 TypeScript 语言中,如果类型` A ` 可以被赋值为类型` B ` ,那么类型 ` A ` 称为父类型,类型 ` B ` 称为子类型。TypeScript 的一个规则是,凡是可以使用父类型的地方,都可以使用子类型 。
88
+ 前面说过,` any ` 类型可以被赋值为任何类型的值。在 TypeScript 语言中,如果类型` A ` 可以被赋值为类型` B ` ,就表示类型 ` B ` 具有类型 ` A ` 的全部特征,这时就称类型 ` B ` 是类型 ` A ` 的超类 。
82
89
83
- 由于任何值都可以赋值给 ` any ` 类型,所以 ` any ` 类型是 TypeScript 所有其他类型的父类型,或者说,所有其他类型都是 ` any ` 的子类型 。
90
+ 那么类型 ` A ` 称为父类型,类型 ` B ` 称为子类型。 TypeScript 的一个规则是,凡是可以使用父类型的地方,都可以使用子类型 。
84
91
85
- 所以, ` any ` 类型是 TypeScript 的一个基础类型,包含了一切可能的值。所有其他类型都可以看成是它的衍生类型,它又被称为顶端类型(top type) 。
92
+ 由于任何值都可以赋值给 ` any ` 类型,所以 ` any ` 类型是 TypeScript 所有其他类型的父类型,或者说,所有其他类型都是 ` any ` 的子类型 。
86
93
87
94
## unknown 类型
88
95
89
- 为了解决` any ` 类型“污染”其他变量的问题,TypeScript 3.0 引入了[ ` unknown ` 类型] ( https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#new-unknown-top-type ) 。它与` any ` 含义相同,表示类型不确定,但是使用上有一些限制 ,可以视为严格版的` any ` 。
96
+ 为了解决` any ` 类型“污染”其他变量的问题,TypeScript 3.0 引入了[ ` unknown ` 类型] ( https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#new-unknown-top-type ) 。它与` any ` 含义相同,表示类型不确定,可能是任意类型,但是它的使用有一些限制,不像 ` any ` 那样自由 ,可以视为严格版的` any ` 。
90
97
91
98
` unknown ` 跟` any ` 的相似之处,在于所有类型的值都可以分配给` unknown ` 类型。
92
99
@@ -113,7 +120,7 @@ let v2:number = v; // 报错
113
120
114
121
上面示例中,变量` v ` 是` unknown ` 类型,赋值给` any ` 和` unknown ` 以外类型的变量都会报错,这就避免了污染问题,从而克服了` any ` 类型的一大缺点。
115
122
116
- 另外,也不能直接调用 ` unknown ` 类型变量的方法和属性。
123
+ 其次,不能直接调用 ` unknown ` 类型变量的方法和属性。
117
124
118
125
``` typescript
119
126
let v1: unknown = { foo: 123 };
@@ -167,15 +174,15 @@ if (typeof s === 'string') {
167
174
168
175
这样设计的目的是,只有明确` unknown ` 变量的实际类型,才允许使用它,防止像` any ` 那样可以随意乱用,“污染”其他变量。类型细化以后再使用,就不会报错。
169
176
170
- 总之,` unknown ` 可以看作是更安全的` any ` ,凡是需要设为` any ` 的地方 ,通常都应该优先考虑设为` unknown ` 。
177
+ 总之,` unknown ` 可以看作是更安全的` any ` 。一般来说 ,凡是需要设为` any ` 类型的地方 ,通常都应该优先考虑设为` unknown ` 类型 。
171
178
172
- 由于 ` unknown ` 类型的变量也可以被赋值为任意其他类型,所以其他类型 (除了` any ` )都可以视为它的子类型。所以,它和 ` any ` 一样都属于 TypeScript 的顶端类型 。
179
+ 在集合论上, ` unknown ` 也可以视为所有其他类型 (除了` any ` )的全集,所以它和 ` any ` 一样,也属于 TypeScript 的顶层类型 。
173
180
174
181
## never 类型
175
182
176
- 类型也可能是空集,即不包含任何类型。为了逻辑的完整性 ,TypeScript 把这种情况也当作一种类型,叫做 ` never ` 类型 。
183
+ 为了保持与集合论的对应关系,以及类型运算的完整性 ,TypeScript 还引入了“空类型”的概念,即该类型为空,不包含任何值 。
177
184
178
- ` never ` 类型表示不可能的类型,也就是不可能有任何值属于这个类型 。
185
+ 由于不存在任何属于“空类型”的值,所以该类型被称为 ` never ` ,即不可能发生这样的值 。
179
186
180
187
``` typescript
181
188
let x: never ;
@@ -199,9 +206,9 @@ function fn(x:string|number) {
199
206
}
200
207
```
201
208
202
- 上面示例中,参数变量` x ` 可能是字符串,也可能是数组 ,判断了这两种情况后,剩下的 ` else ` 分支里面,` x ` 就是` never ` 类型了。
209
+ 上面示例中,参数变量` x ` 可能是字符串,也可能是数值 ,判断了这两种情况后,剩下的最后那个 ` else ` 分支里面,` x ` 就是` never ` 类型了。
203
210
204
- 任何类型的变量都可以赋值为 ` never ` 类型 。
211
+ ` never ` 类型的一个重要特点是,可以赋值给任意其他类型 。
205
212
206
213
``` typescript
207
214
function f(): never {
@@ -215,4 +222,7 @@ let v3:string = f(); // 正确
215
222
216
223
上面示例中,函数` f() ` 会抛错,所以返回值类型可以写成` never ` ,即不可能返回任何值。各种其他类型的变量都可以赋值为` f() ` 的运行结果(` never ` 类型)。
217
224
218
- 前面说过,在 TypeScript 中,如果类型` A ` 可以被赋值为类型` B ` ,那么类型` B ` 就称为类型` A ` 的子类型。所以,` never ` 类型可以视为所有其他类型的子类型,表示不包含任何可能的值,这种情况叫做“尾端类型”(bottom type),` never ` 是 TypeScript 唯一的尾端类型。
225
+ 为什么` never ` 类型可以赋值给任意其他类型呢?这也跟集合论有关,空集是任何集合的子集。TypeScript 就相应规定,任何类型都包含了` never ` 类型。因此,` never ` 类型是任何其他类型所共有的,TypeScript 把这种情况称为“底层类型”(bottom type)。
226
+
227
+ 总之,TypeScript 有两个“顶层类型”(` any ` 和` unknown ` ),但是“底层类型”只有` never ` 唯一一个。
228
+
0 commit comments